Error while uploading file to Amazon S3 bucket - android

When I run my app and logins with google account, it gives me the cognito provider. Now I am trying to upload a file to S3 bucket from the app. First I am trying to upload a file from my local laptop, then I will change it to upload from the app. Here is my code
provider = new CognitoCachingCredentialsProvider(mContext,
AWS_ACCOUNT_ID, IDENTITY_POOL_ID, UNAUTH_ROLE_ARN, AUTH_ROLE_ARN,Regions.EU_WEST_1);
client = new CognitoSyncManager(mContext, IDENTITY_POOL_ID, Regions.EU_WEST_1, provider);
String BUCKET_NAME = "uni-cloud";
String access_key = "something";
TransferManager transferManager = new TransferManager(provider);
File file = new File("E:\\Google Drive\\Year 3\\Project\\dummy.docx");
Log.e("Cognito Provider ID","Data " + provider.getIdentityId());
try {
Upload upload = transferManager.upload(BUCKET_NAME,access_key, file);
while (!upload.isDone()){
Log.i("upload","Uploading");
}
Log.i("upload","Uploaded");
}catch(Exception e) {Log.i("Upload", "Error while uploading");}
This is what I get in my logs.
03-04 17:27:57.789 24584-24712/com.unicloud.mittal I/upload﹕ Uploading
03-04 17:27:57.789 24584-24712/com.unicloud.mittal I/upload﹕ Uploading
03-04 17:27:57.799 24584-24712/com.unicloud.mittal I/upload﹕ Uploaded
Now when I check the S3 bucket on AWS site, it doesn't show the file. There are no errors but the file is also not uploaded. It would be helpful if you can point out my mistake.
Thanks.

I have solved this issue. If someone is looking for the method, here it is. It was not uploading because it didn't have permission to read the file. I gave the permissions in AndroidManifest.xml and it worked.
Permission in AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Working code
TransferManager transferManager = new TransferManager(provider);
String bucket = "uni-cloud";
File file = new File("//sdcard//Download//cw.pdf");
if(file.exists())
{
Log.e(TAG,"File found " + file.getName());
}
else {
Log.e(TAG,"File not found");
}
Upload upload = transferManager.upload(bucket, file.getName(), file);
while (!upload.isDone()){
//Show a progress bar...
TransferProgress transferred = upload.getProgress();
Toast.makeText(this, "Uploading... ", Toast.LENGTH_LONG).show();
Log.i("Percentage", "" +transferred.getPercentTransferred());
}
Toast.makeText(this, "Uploaded", Toast.LENGTH_LONG).show();

Related

"No content provider" error whenever I attempt to upload a file on Android device

Lately I've been having a problem trying to upload a file to storage on Android. It works perfectly fine on the Unity Editor, but whenever I run it on my Android I keep getting this error instead:
System.AggregateException: Exception of type 'System.AggregateException' was thrown.
Firebase.Storage.StorageException: No content provider:
/storage/emulated/0/Android/data/com.Comp.App/files/Uploads/ppp/master.json
Here is the code I use to upload files to storage:
Firebase.Storage.StorageReference f_ref = storage_ref.Child(referencePath);
print("Reference path: " + referencePath);
// Upload the file
f_ref.PutFileAsync(filePath)
.ContinueWith((Task<StorageMetadata> task) =>
{
if (task.IsFaulted || task.IsCanceled)
{
Debug.Log(task.Exception.ToString());
print("Couldn't upload " + filePath);
// Uh-oh, an error occurred!
}
else {
Firebase.Storage.StorageMetadata metadata = task.Result;
string download_url = metadata.DownloadUrl.ToString();
Debug.Log("download url = " + download_url);
}
});
The file is stored in a persistent file path that depends on the device. I tried purposefully uploading a non-existing file path and I received a "FileNotFound" exception instead, so I'm certain the path of the file I'm trying to upload is correct.
I would greatly appreciate any help in figuring out what this exception means and how to fix it. Thanks in advance!
Use an inputStream and putStream instead :
InputStream is = new FileInputStream(filePath);
f_ref.putStream(is).....;
Maybe you should pass an URI of the form Like This
file:///sdcard/yourFilePath
I had this same problem and E. Abdel's answer led me on the right track. I was trying to upload a file saved with a BinaryFormatter
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + pathToFile);
bf.Serialize(file, currentPlayer);
file.Close();
I was getting the exact same error, then I tried a different way of uploading it. Instead of PutFileAsync, use PutStreamAsync, I guess this needs to be used for serialized files with BinaryFormatter.
// File located on disk
string local_file = Application.persistentDataPath + pathToFile;
// Create a reference to the file you want to upload
StorageReference storage_ref = FirebaseStorage.DefaultInstance.RootReference;
StorageReference player_ref = storage_ref.Child("test");
Stream stream = new FileStream(local_file, FileMode.Open);
player_ref.PutStreamAsync(stream).ContinueWith((Task<StorageMetadata> task) =>
{
if (task.IsFaulted || task.IsCanceled)
{
Debug.Log(task.Exception.ToString());
// Uh-oh, an error occurred!
}
else
{
// Success
}
});
In my case i had the same error (Firebase.Storage.StorageException: No content provider) only to upload files with Android.
Reading the E. Abdel's answer I have found these following solution in C# to Unity.
StreamReader stream = new StreamReader(file_path);
StorageReference storage_ref = storageRef.Child(file_name_to_storage);
storage_ref.PutStreamAsync(stream.BaseStream)
.ContinueWith((Task<StorageMetadata> task) => {
if (task.IsFaulted || task.IsCanceled)
{
Debug.Log(task.Exception.ToString());
}
else
{
Debug.Log("Finished uploading...");
}
});
It`s works in Unity editor and Android to upload files specifying de file path in my case the file_path is: /storage/emulated/0/file_name.png
Was having same problem. Solved it by putting "file://" in front of the uri and parsing it with Uri.parse as:
val uriString = Uri.parse("file://$uri")
if (metadata != null) {
fileRef.putFile(uriString, metadata).await()
} else {
fileRef.putFile(uriString).await()
}

Android Studios Serialization. Attempt to get length of null array

Okay, so in my project I am trying to serialize a chess game by writing to a folder named data. I did this in eclipse, and it was able to work. However, when I brought it into android studios I got the error of trying to get the length of a null array. Here is my method:
public static void writeData() throws IOException {
System.out.println("WRiting data");
File folder = new File("data" + File.separator);
folder.mkdir();
String[] directories = folder.list();
for (String name : directories) { //error here
File ff = new File(folder + File.separator + name);
if (ff.isDirectory()) {
deleteDirectory(ff);
}
}
//add all user data
for (game u : info.games) {
File f = new File("data" + File.separator + u.name); //make a file with user name
f.mkdir(); //make the file a directory
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(f + File.separator + "game-state"));
//create stream with file name at the end
oos.writeObject(u);
//write objects
oos.close();
}
}
Also, I looked at previous questions and changed my manifest file to allow for the permissions of writing and reading data.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
The app does not crash when I read data. However, it crashes when I try to write data. Going crazy over here. Thank you for your help.
This may be due to marshmellow permission request ,you have to call permission request at runtime .
go through link
https://developer.android.com/training/permissions/requesting.html

android mkdirs not working

i need to save an image from camera on android.
i used the write external storage permission in manifest and i am using this code
File dir = new File(Environment.getExternalStorageDirectory(), "Test");
if (!dir.exists() || !dir.isDirectory())
dir.mkdirs();
String path = dir.getAbsolutePath();
Log.d(TAG, path); //log show the path
File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
Log.d(TAG, file.getAbsolutePath()); //again path is shown here
outStream = new FileOutputStream(file);
outStream.write(bytes);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + bytes.length); //fail here
} catch (FileNotFoundException e) {
Log.d(TAG, "not done"); //error is here (this exception is thrown)
} catch (IOException e) {
Log.d(TAG, "not");
} finally { }
i also tried mkdir() instead of mkdirs() same result.
any idea what went wrong in the code?
thanks
For those not as experienced like me. I fought this issue, lost hair for some time. I am targeting api 21 (for compatibility sake) and it worked on lollipop but on marshmallow it would not create the directory. I did have the "uses" permission in the manifest but it still would not work. Apparently in Marshmallow when you install with Android studio it never asks you if you should give it permission it just quietly fails, like you denied it. You must go into Settings, apps, select your application and flip the permission switch on.
Some one like me who was trying in Android10. Please use below API in manifest:
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
Latest Update From Google:
After you update your app to target Android 11, the system ignores the requestLegacyExternalStorage flag.
Did you put
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
in your AndroidManifest? If you are using android M you must request user permission to write on sd, look here an example
IDIOT ME! i have used the Manifest Permission but when installed the app on phone i didnt grant permission for storage!... i understand a negative on this question... but i hope if someone else face the same..check your phone permission. sorry all for inconvenience.
you have created directory, not file. Create new file with following code
File file = new File(dir.getAbsolutePath() + "/Pic.jpg");
file.createNewFile()
if you are testing on android M, you should probably check Settings > App > Permission to see if permission to access storage is granted. This saved me.
if you already allowed R/W permission(Runtime Permission too) and still doesn't work add this below mentioned line in your AndroidManifest.xml
<application
........
........
android:requestLegacyExternalStorage="true">
Note: this must required if you'r targeting Android 10+
Starting from API 30 you can only write in your app-specific files
File dir = new File(context.getFilesDir(), "YOUR_DIR");
dir.mkdirs();
or in the external storage of your app Android/data
File dir = new File(myContext.getExternalFilesDir("FolderName"),"YOUR_DIR");
UPDATE
this answer provided another solution https://stackoverflow.com/a/65744517/8195076
UPDATE
another way is to grant this permission in manifest
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
like this answer https://stackoverflow.com/a/66968986/8195076
Try this. Provide runtime permission for marshmallow it is perfectly work in my Application code :
private String getFilename(String strFileName) {
String filepath = Environment.getExternalStorageDirectory().getPath();
File fileBase = new File(filepath, "Test");
if (!fileBase.exists()) {
fileBase.mkdirs();
}
return (file.getAbsolutePath() + "/" + strFileName + file_exts[currentFormat]);
}
new File(getFilename(edt.getText().toString().trim()))
outputFile = new File(apkStorage + "/" + downloadFileName );
//Create Output file in Main File
//Create New File if not present
if (!outputFile.exists()) {
isExternalStorageWritable();
outputFile.getParentFile().mkdirs();
outputFile.createNewFile();
Log.e(TAG, "File Created");
OutputStream fos = new FileOutputStream(outputFile);//Get OutputStream for NewFile Location
InputStream fis = c.getInputStream();//Get InputStream for connection
byte[] buffer = new byte[1024];//Set buffer type
int len1 = 0;//init length
while ((len1 = fis.read(buffer)) >0) {
fos.write(buffer, 0, len1);//Write new file
}
//Close all connection after doing task
fos.close();
fis.close();
I wrote this code for creating a file, but it is not working in android 11
when writing code for android API 29 and above use the following permission in your application manifest (AndroidManifest.xml)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
Adjust your code to read like the following
ActivityCompat.requestPermissions(this, new String[]
{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
PackageManager.PERMISSION_GRANTED);
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
file = new File(Environment.getExternalStorageDirectory().getPath(), "TestDirectory/Document/");
if (!file.exists()) {
try {
file.mkdirs();
} catch (Exception e) {
e.printStackTrace();
}
}

Downloading Object from Android's Amazon s3 makes file unreadable

Currently, I'm trying to download a file I have in a bucket on Amazon s3. I'm using this code to debug, because I always get an EN0ENT / file not found when I try to read from the file in the end.
String str_FilePathInDevice = "/sdcard/" + "/"
+ "RestoreFolderName" + "/" + "filname.extention";
File file = new File(str_FilePathInDevice);
String str_Path = file.getPath().replace(file.getName(), "");
File filedir = new File(str_Path);
try {
filedir.mkdirs();
file.createNewFile();
} catch (Exception ex1) {
}
System.out.println(file.toString());
System.out.println(file.canRead());
System.out.println(file.length());
TransferObserver observer2 = transferUtility.download(
"arabianbucket", /* The bucket to upload to */
"demo.txt", /* The key for the uploaded object */
file /* The file where the data to upload exists*/
);
System.out.println(file.toString());
System.out.println(file.canRead());
System.out.println(file.length());
the file.canread() ends up being flipped from true to false after the transferutility.download link. I'm not particularly sure why this is the case. Does anyone know how to successfully read from an object in Amazon s3? In my manifest, I've already flipped the permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Thank you!
TransferUtility offers asynchronous transfers. In your code transferUtility.download initiates a download and the download happens in a background thread so as not to block the main thread. I don't recommend any file operation until the transfer is done. You can attach a listener to the observer and listens to status and progress changes. See Store and Retrieve Files with Amazon S3 for more information.

"Permission denied for the attachment" (on Gmail 5.0) trying to attach file to email intent

This question has been posted before, but there was no clear or accepted answer and all of the solutions provided that were supposed to "work" didn't for me. See here: Gmail 5.0 app fails with "Permission denied for the attachment" when it receives ACTION_SEND intent
I have an app which builds up data in a text file and needs to send the text file along in an email, automatically attaching it. I have tried many ways to get this to attach, and it apparently works for Gmail 4.9 and below but 5.0 has some new permission features disabling it from doing what I wish.
Intent i = new Intent(Intent.ACTION_SEND);
String to = emailRecipient.getText().toString();
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
i.putExtra(Intent.EXTRA_SUBJECT, "Pebble Accelerometer Data");
i.putExtra(Intent.EXTRA_TEXT, "Attached are files containing accelerometer data captured by SmokeBeat Pebble app.");
String[] dataPieces = fileManager.getListOfData(getApplicationContext());
for(int i2 = 0; i2 < dataPieces.length; i2++){
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + dataPieces[i2])));
}
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext()))));
Log.e("file loc", getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext()));
try {
startActivity(Intent.createChooser(i, "Send Email"));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(Main.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
The datapieces might be empty yes but the current file line below the for loop is always reliable and always attaches something.
I have tried changing
Uri.fromFile()
to
Uri.parse()
When I do that, it attaches, but Gmail then crashes and when I check the logcat it's because of a null pointer. This is most likely because Gmail has no access to the file and therefore results as null.
I've also tried using
getCacheDir()
instead of
getFilesDir()
and it has the same outcome.
What am I doing wrong here, and how should I go about fixing it? Some example code would be really, really handy because I am new to Android development and explaining what I need to do without some sort of push off probably won't end up helping.
Thanks a lot.
Alright guys. Took a break and came back, figured it out.
Here's how it works, you need to have write/read permissions to external storage, so add these permissions to your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Then, your file has to be copied from your app's internal storage directory into the app's external directory. I recommend you use internal storage, and that's what I'm doing here so you can figure out SD cards yourself.
Here is the block of code that does the magic. Logs are included but you can remove them by all means.
public void writeToExternal(Context context, String filename){
try {
File file = new File(context.getExternalFilesDir(null), filename); //Get file location from external source
InputStream is = new FileInputStream(context.getFilesDir() + File.separator + filename); //get file location from internal
OutputStream os = new FileOutputStream(file); //Open your OutputStream and pass in the file you want to write to
byte[] toWrite = new byte[is.available()]; //Init a byte array for handing data transfer
Log.i("Available ", is.available() + "");
int result = is.read(toWrite); //Read the data from the byte array
Log.i("Result", result + "");
os.write(toWrite); //Write it to the output stream
is.close(); //Close it
os.close(); //Close it
Log.i("Copying to", "" + context.getExternalFilesDir(null) + File.separator + filename);
Log.i("Copying from", context.getFilesDir() + File.separator + filename + "");
} catch (Exception e) {
Toast.makeText(context, "File write failed: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); //if there's an error, make a piece of toast and serve it up
}
}
Encountered the same attachment denied. Permissions in manifest did not have any effect, rather do not have an effect any more since API 23. Finally solved it as follows.
1st need to check and grant permissions on run-time, I did it in my main activity:
public static final int MY_PERMISSIONS_REQUEST_READ_STORAGE=10001;
private void checkPermission(){
if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (this.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
// Show an explanation to the user asynchronously
} else {
// No explanation needed, we can request the permission.
this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_STORAGE);
}
}
}
Now when sending, create a file in PUBLIC directory (tried saving to my app folder - same denial problem)
public File createFile(){
String htmlStr="<!DOCTYPE html>\n<html>\n<body>\n<p>my html file</p></body></html>";
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "aimexplorersummary.html");
try {
FileWriter writer = new FileWriter(file ,false);
writer.write(htmlStr);
}
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
return file;
}
Now compose sending intent and putExtra with uri to your file which is in public storage that user must grant permissions to and that causes no problem now
public void send(){
Intent intentSend = new Intent(android.content.Intent.ACTION_SEND);
intentSend.setType("text/html");
File file = createFile();
if(file!=null){
intentSend.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
}
startActivity(Intent.createChooser(intentSend, "Send using:"));
}

Categories

Resources