Android: java.io.FileNotFoundException: Not a whole file - java

I make an chat app for practice and
tried to use my add1.png image in my drawable folder as a default profile image whether user put the image or not
here's my code snipet
if (imageUri == null) { //when user has no image
//use default image as a profile image that in drawable folder
imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
"://" + getResources().getResourcePackageName(R.drawable.add1)
+ '/' + getResources().getResourceTypeName(R.drawable.add1)
+ '/' + getResources().getResourceEntryName(R.drawable.add1));
}
//insert into firebase storage
FirebaseStorage.getInstance().getReference().child("userImages").child(uid).putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {...}
In the event that run the app exception has occurred but the default image(add1.png) be inserted into firebase storage properly.
here's the exception.
W/UploadTask: could not retrieve file size for upload android.resource://com.example.harag.myapplication/drawable/add1
java.io.FileNotFoundException: Not a whole file
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:812)
at android.content.ContentResolver.openFileDescriptor(ContentResolver.java:749)
at com.google.firebase.storage.UploadTask.<init>(Unknown Source)
at com.google.firebase.storage.StorageReference.putFile(Unknown Source)
at com.example.harag.myapplication.SignUpActivity$2$1.onComplete(SignUpActivity.java:92)
at com.google.android.gms.tasks.zzf.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
thank you!

You need to use UploadTask.UploadTask which you can use to manage and monitor the status of the upload.
Uri file = Uri.fromFile(new File("path/to/images/rivers.jpg"));
StorageReference riversRef = storageRef.child("images/"+file.getLastPathSegment());
uploadTask = riversRef.putFile(file);
// Register observers to listen for when the download is done or if it fails
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
Uri downloadUrl = taskSnapshot.getDownloadUrl();
}
});
Firebase Upload Files

You can try below code.
Uri uri = Uri.parse("android.resource://org.xyz.abc/drawable/myimage");
or
Uri uri=Uri.parse("android.resource://"+context.getPackageName()+"/drawable/myimage");

Related

java.io.FileNotFoundException: (Permission denied) Only in Oreo

I am downloading photos to smartphone. For versions lower than Oreo, there's no problem. But for Oreo, my code isn't not working. I tried this code in Emulator:
I implemented a function to save an image to external storage.
private void saveImageToExternalStorage(Bitmap finalBitmap,String name) {
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/xx");
myDir.mkdirs();
String fname = name + ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
}
catch (Exception e) {
e.printStackTrace();
}
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
I am requesting permissions with dexter library.
Dexter.withActivity(MainActivity.this)
.withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener(new PermissionListener() {
#Override
public void onPermissionGranted(PermissionGrantedResponse response) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
if (!prefs.getBoolean("firstTime", false)) {
task.execute();
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("firstTime", true);
editor.commit();
}
}
#Override
public void onPermissionDenied(PermissionDeniedResponse response) {
Toast.makeText(MainActivity.this, "You need to allow permission if you want to use camera", Toast.LENGTH_LONG).show();
}
#Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
token.continuePermissionRequest();
Toast.makeText(MainActivity.this, "You need to allow permission if you want to use camera", Toast.LENGTH_LONG).show();
}
}).check();
I save images with asynctask
final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
#Override
protected void onPreExecute()
{
this.dialog = new ProgressDialog(MainActivity.this);
this.dialog.setMessage(getString(R.string.newfeature));
this.dialog.setCancelable(false);
this.dialog.setOnCancelListener(new DialogInterface.OnCancelListener()
{
#Override
public void onCancel(DialogInterface dialog)
{
// cancel AsyncTask
cancel(false);
}
});
this.dialog.show();
}
#Override
protected Void doInBackground(Void... params)
{
// do your stuff
Bitmap myBitmap2 = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.im2);
saveImageToExternalStorage(myBitmap2,"imag2");
myBitmap2.recycle();
return null;
}
#Override
protected void onPostExecute(Void result)
{
//called on ui thread
if (this.dialog != null) {
this.dialog.dismiss();
}
}
#Override
protected void onCancelled()
{
//called on ui thread
if (this.dialog != null) {
this.dialog.dismiss();
}
}
};
I can see Storage permission is granted when I look Settings --> Apps for my app. But images are not saved correctly. In fact images are saved but all of them is green square like this.
As a result, it gives permission denied error although permission is granted.
09-21 13:11:08.023 17636-17765/xx.xx W/System.err: java.io.FileNotFoundException: /storage/emulated/0/Pictures/xx/imag2.jpg (Permission denied)
09-21 13:11:08.024 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.open0(Native Method)
09-21 13:11:08.024 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.open(FileOutputStream.java:308)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:238)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:180)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity.saveImageToExternalStorage(MainActivity.java:804)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity.access$000(MainActivity.java:62)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity$1.doInBackground(MainActivity.java:119)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at xx.xx.MainActivity$1.doInBackground(MainActivity.java:89)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:333)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
09-21 13:11:08.033 17636-17765/xx.xx W/System.err: at java.lang.Thread.run(Thread.java:764)
Access Sd-Card's files
Use DOCUMENT_TREE dialog to get sd-card's Uri.
Inform user about how to choose sd-card on the dialog. (with pictures or gif animations)
// call for document tree dialog
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
On onActivityResult you'll have the selected directory Uri. (sdCardUri)
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_OPEN_DOCUMENT_TREE:
if (resultCode == Activity.RESULT_OK) {
sdCardUri = data.getData();
}
break;
}
}
Now must check if the user,
a. selected the sd-card
b. selected the sd-card that our file is on (some devices could have multiple sd-cards).
We check both a and b by finding the file through the hierarchy, from sd root to our file. If file found, both of a and b conditions are acquired.
//First we get `DocumentFile` from the `TreeUri` which in our case is `sdCardUri`.
DocumentFile documentFile = DocumentFile.fromTreeUri(this, sdCardUri);
//Then we split file path into array of strings.
//ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "myImage.jpg"}
// There is a reason for having two similar names "MyFolder" in
//my exmple file path to show you similarity in names in a path will not
//distract our hiarchy search that is provided below.
String[] parts = (file.getPath()).split("\\/");
// findFile method will search documentFile for the first file
// with the expected `DisplayName`
// We skip first three items because we are already on it.(sdCardUri = /storage/extSdCard)
for (int i = 3; i < parts.length; i++) {
if (documentFile != null) {
documentFile = documentFile.findFile(parts[i]);
}
}
if (documentFile == null) {
// File not found on tree search
// User selected a wrong directory as the sd-card
// Here must inform user about how to get the correct sd-card
// and invoke file chooser dialog again.
} else {
// File found on sd-card and it is a correct sd-card directory
// save this path as a root for sd-card on your database(SQLite, XML, txt,...)
// Now do whatever you like to do with documentFile.
// Here I do deletion to provide an example.
if (documentFile.delete()) {// if delete file succeed
// Remove information related to your media from ContentResolver,
// which documentFile.delete() didn't do the trick for me.
// Must do it otherwise you will end up with showing an empty
// ImageView if you are getting your URLs from MediaStore.
//
Uri mediaContentUri = ContentUris.withAppendedId(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
longMediaId);
getContentResolver().delete(mediaContentUri , null, null);
}
}
Note:
You must provide access permission to the external storage inside your manifest and for os>=Marshmallow inside the app.
https://stackoverflow.com/a/32175771/2123400
Edit Sd-Card's Files
For editing an existing image on your sd-card you don't need any of above steps if you want to invoke another app to do it for you.
Here we invoke all the activities (from all the installed apps) with the capability of editing the images. (Programmers mark their apps in the manifest for its capabilities to provide accessibility from other apps (activities)).
on your editButton click event:
String mimeType = getMimeTypeFromMediaContentUri(mediaContentUri);
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_EDIT).setDataAndType(mediaContentUri, mimeType).putExtra(Intent.EXTRA_STREAM, mediaContentUri).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION), "Edit"), REQUEST_CODE_SHARE_EDIT_SET_AS_INTENT);
and this is how to get mimeType:
public String getMimeTypeFromMediaContentUri(Uri uri) {
String mimeType;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
ContentResolver cr = getContentResolver();
mimeType = cr.getType(uri);
} else {
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
.toString());
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
fileExtension.toLowerCase());
}
return mimeType;
}
Note:
On Android KitKat(4.4) don't ask the user to select the sd-card because on this version of Android DocumentProvideris not applicable, hence we have no chance to have access to the sd-card with this approach.
Look at the API level for the DocumentProvider
https://developer.android.com/reference/android/provider/DocumentsProvider.html
I couldn't find anything that works on Android KitKat(4.4). If you found anything useful with KitKat please share with us.
On versions below the KitKat access to sd-card is already provided by the OS.

upload to firebase success only when debug [duplicate]

This question already has an answer here:
Can't get download url from Firebase Storge in Android [duplicate]
(1 answer)
Closed 4 years ago.
i am trying to upload a file to firestore (with putBytes) and then its url to the database.
So i am doing the db update in the "onSuccessListener" of the storage task like this:
private void uploadFile(byte[] bookImg, final String bookName){
if(mUploadTask != null && mUploadTask.isInProgress()){
//... upload in progress ...
} else {
if (bookImg != null) {
StorageReference fileRef = mStorageRef.child(bookName);
mUploadTask = fileRef.putBytes(bookImg)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
StorageReference refToUploadedPic = taskSnapshot.getMetadata().getReference();
Uri uploadedPicUri = refToUploadedPic.getDownloadUrl().getResult();
Upload upload = new Upload(bookName,
uploadedPicUri.toString());
String uploadId = mDatabaseRef.push().getKey(); //creates new entry on db
mDatabaseRef.child(uploadId).setValue(upload); //saves the file metadata on the new entry
}
})
.addOnFailureListener(new OnFailureListener() {
//... handle Failure...
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
//... handle onProgress...
});
} else {
Toast.makeText(this, "NoFile", Toast.LENGTH_LONG).show();
}
}
}
the picture is uploaded to the storage but when it gets to this line:
Uri uploadedPicUri = refToUploadedPic.getDownloadUrl().getResult();
i get this error:
java.lang.IllegalStateException: Task is not yet complete
at com.google.android.gms.common.internal.Preconditions.checkState(Unknown Source:8)
at com.google.android.gms.tasks.zzu.zzdq(Unknown Source:4)
at com.google.android.gms.tasks.zzu.getResult(Unknown Source:3)
at com.controllers.BookListActivity$4.onSuccess(BookListActivity.java:302)
at com.controllers.BookListActivity$4.onSuccess(BookListActivity.java:289)
at com.google.firebase.storage.zzi.zza(Unknown Source:13)
at com.google.firebase.storage.zzac.zza(Unknown Source:2)
at com.google.firebase.storage.zzaf.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6665)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
the thing is that when i am debugging and step into this line (with F7) everything works as expected....
any help??
think you need to add an OnSuccessListener<Uri> there:
refToUploadedPic.getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
}
});

CardView Click to download PDF

i want to download a pdf file when i click on the card view, this is how i declare it inside a viewholder..
holder.pdfLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
final DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
baptistDatabase.child(post_key).child("pdflocation").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String baptistpdf = dataSnapshot.getValue(String.class);
Uri uri = Uri.parse(baptistpdf);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
Long reference = dm.enqueue(request);
}
and this is my LogCat
FATAL EXCEPTION: main
Process: com.packageone.winter.tkpchanmariunitaizawl, PID: 13072
java.lang.NullPointerException: uriString
at android.net.Uri$StringUri.<init>(Uri.java:475)
at android.net.Uri$StringUri.<init>(Uri.java:465)
at android.net.Uri.parse(Uri.java:437)
at com.packageone.winter.tkpchanmariunitaizawl.BaptistS_pdf.BaptistPdfFiles$1$2$1.onDataChange(BaptistPdfFiles.java:108)
My Database Goes like this.
Baptists -> Pdf Files -> push() -> (key)pdflocation - "Storage Location Link"
How i want is when i Click on the Card view, i just want to Download the Pdf, because i just cant refer to one single Link as it keeps on changing when a new pdf files are uploaded..
Help...

Best way to get the downloadUrl of thumbnail generated by Firebase Cloud Function

StorageReference newfilepath = mStorage.child("User Submission Images").child(user_id).child("photo1g.jpg");
newfilepath.putFile(photo1ImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
final Uri dwnldUri = task.getResult().getDownloadUrl();
businessDBRef.child(user_id).child("photos1").setValue(dwnldUri.toString());
StorageReference thumbpath = mStorage.child("User Submission Images").child(user_id);
thumbpath.child("thumb_photo1v.jpg").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
businessDBRef.child(user_id).child("thumb1").setValue(uri.toString());
}
});
mProgess.dismiss();
Toast.makeText(getApplicationContext(), "Upload Successful", Toast.LENGTH_SHORT).show();
}
});
After the image gets uploaded i try to pass the download url of the thumbnail into the database but i assume that my code executes faster than the creation of the thumbnail so i get this
StorageException has occurred.
Object does not exist at location.
When checking the Firebase storage the thumbnail is there with the download url accessible. Is there any workaround for this? maybe a way to wait for the thumbnail to generate first and then get the download URl??

How do I save an image url from Firebase Storage to Firebase realtime data base, the image from my device

I have been trying to save the url to the firebase realtime database here is my code
Uri uri = data.getData();
StorageReference filePath =
mStorage.child("Photos").child(currentFirebaseUser.getUid());
filePath.putFile(uri).addOnSuccessListener(new
OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(ManageActivity.this, "Image upload
successful",Toast.LENGTH_LONG).show();
progressDialog.dismiss();
profile_image_url = taskSnapshot.getDownloadUrl();
driver.child("profile image").setValue(profile_image_url);
the logcat shows that its a stack over flow error, here is the logcat:
FATAL EXCEPTION: main
Process: com.example.user.drivergeofire, PID: 6758
java.lang.StackOverflowError
at java.util.HashMap$ValueIterator.<init>(HashMap.java:836)
at java.util.HashMap$ValueIterator.<init>(HashMap.java:836)
at java.util.HashMap.newValueIterator(HashMap.java:908)
at java.util.HashMap$Values.iterator(HashMap.java:936)
at com.google.android.gms.internal.zh.zzas(Unknown Source)
at com.google.android.gms.internal.zg.zzao(Unknown Source)
my research on StackOverflow erros state that it is cause by having may views, I don't have any there.
Your assistance will be veery much appreciated
To get tue URL from the saved file use:
mStorage.child("Photos").child(currentFirebaseUser.getUid()).getDownloadUrl().getResult();

Categories

Resources