Save Uri as a file android - java

So in my app it is receiving an image from another application
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
handleSendImage(intent); // Handle single image being sent
public void handleSendImage(Intent a)
{
Uri pic = (Uri) a.getParcelableExtra(Intent.EXTRA_STREAM);
}
From here I want to save the Uri as an image in my image gallery.
I know how to save a file in the gallery I am just not sure how I get the Uri in the correct format to save it. I know it contains the image because picView.setImageURI(pic); causes the picture to appear in my activity. I just want to be able to save that image into the gallery. Any ideas on how I would do that? I thought that I could convert the ImageView to a bitmap and go from there but that seems really inefficient to me and there has to be a better way to do it. Since I know you can create Uris from Files but can you create a File from a Uri?

Related

Can't play video in videoview android studio?

I know that there is too many solutions were given, but I can't get the exact solution. My problem is that I have picked one video from internal storage device and after picking video then I have converted to String and set the video to videoView but then also it shows that "Can't play this video" in videoView.
can anyone please help me to find out the solution :(
here is my code
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/Download/videos.mp4");
Log.d("video",""+file);
if (file.exists()) {
Uri uri = Uri.fromFile(file);
String video = String.valueOf(uri);
Log.d("video",""+uri);
videoView.setMediaController(new MediaController(this));
videoView.setVideoURI(Uri.parse(video));
videoView.requestFocus();
videoView.start();
}else {
Toast.makeText(this, "No video found", Toast.LENGTH_SHORT).show();
}
With scoped storage (required from API 30) you can't access files directly unless you request the MANAGE_EXTERNAL_STORAGE (on Google Play you need to request it to Google).
The new way is to use the file uri. You can try those ways:
Ask the user to select the file.
private final ActivityResultLauncher<String[]> openDoc =
registerForActivityResult(new ActivityResultContracts.OpenDocument(),
new ActivityResultCallback<Uri>() {
#Override
public void onActivityResult(Uri uri) {
// use uri
}
});
Call it with:
// Use the mimetype you want (optional). Like "text/plain"
openDoc.launch(new String[]{"text/plain"});
Read more here
Get the Media file uri with MediaStore
Read more here
You'll also need the READ_EXTERNAL_STORAGE permission if the file was not created by your app.

URL requested does not match the just-created upon image upload to Firebase

An image is uploaded to the FirebaseStorage and it gets an URL. Then, a reference is created in FirebaseDatabase where some text is stored along with the image URL of the uploaded image.
Below is whole code which is basically responsible for both uploading the image to FirebaseStorage and creating the database reference for it with a String value of the URL of that image along with a couple of other strings under a uid in database:
private void startPosting(){
final String title_val = et_title.getText().toString().trim();
final String desc_val = et_description.getText().toString().trim();
StorageReference filepath = mStorage.child("Post_images").child(resultUri.getLastPathSegment());
filepath.putFile(resultUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Uri downloadUrl = taskSnapshot.getDownloadUrl();
DatabaseReference newPost = mDatabase.push();
newPost.child("title").setValue(title_val);
newPost.child("description").setValue(desc_val);
newPost.child("image").setValue(downloadUrl.toString());
finish();
}
});
}
When I upload an image from my phone (camera shot or gallery) it successfully stores it in the FirebaseStorage and simultaneously creates a database reference in FirebaseDatabase. And about half of the time it works, the URL in the database "image" and the URL in the storage under "Post_images" MATCH, and the app works just as intended.
BUT, also about half of the time they DO NOT MATCH, in fact their (?alt=media&token...) latter parts, while the filepaths prior to that are the same.
Here is an example of the non-matching URLs error:
This is the URL of the image in the FirebaseStorage:
And this is the URL in the FirebaseDatabase which is supposed to be the same:
But it's NOT, their latter parts (?alt=media&token...) are different...
I've checked onto the Android Monitor and it obviosly tries to get the URL listed in the database, but such does not exist anymore:
I've checked, copied and pasted the URL, it's not working (error 403, image not found). So I'm really confused, seems to me that this method doesn't give me the correct URL obviously:
Uri downloadUrl = taskSnapshot.getDownloadUrl();
Any ideas and help will be appreciated!

Share video from Android raw folder to any app

I am making one app to allow user to share all video from any sharing app. My issue is file attached successfully but the file content is not attaching. below is my full source code. Let me know where I am making a mistake.
private void shareVideo() {
Intent localIntent = new Intent("android.intent.action.SEND");
Uri localUri = Uri.fromFile(new File(CorporateAdaptor.this.rawVideoId + ".mp4"));
String str = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(localUri.toString()));
localIntent.setType(str);
localIntent.setAction("android.intent.action.SEND");
if (str == null) {
str = "*/*";
}
localIntent.setType(str);
localIntent.putExtra("android.intent.extra.STREAM", localUri);
CorporateAdaptor.this.mContext.startActivity(Intent.createChooser(local Intent, "Where you want to share?"));
}
This is my code that was I am using when user click on the share button. It will open a share dialog and when I select the gmail app, the file is attached but it's showing me a toast message "Couldn't find attachment". And when I click on send email file was not sending.

How can I delete a pre-existing image from storage before re-downloading using DownloadManager?

I am writing code for an Android app using Eclipse that is supposed to download an image from a URL (which is generated by the app, elsewhere in the code, using GPS information), then attach the newly downloaded image to an e-mail to be sent. I am able to, in general, accomplish this without much issue.
My problem is this: I only want one image downloaded by the app to be present in the device's external storage at any given time. Deleting the image after the email intent does not work, because because the app doesn't always call onStop or onDestroy when switching to another app to send the email. Time-sensitive deleting of the image will not work either, because I cannot assume that the user will send only one email from the app per hour. I want to give the user the freedom of sending as many of these emails (with one newly downloaded image, each) as they wish.
My current method (which works MOST of the time) is this: in the downloadFile method, simply check for the file's existence (I call it sensorMap.png), then delete it if it exists, before downloading a new one. This SHOULD ensure that there may be only one sensorMap.png image in external storage at any given time (EDIT: it does do this), and that when it comes time to attach the image to the email intent, there will be exactly one image ready to go. Instead, I see that sometimes a second sensorMap image is sometimes being downloaded into storage (i.e. "sensorMap-1.png"), OR the image cannot be attached to the email due to a "File size: 0 bytes" error, OR the image cannot be attached due to a "File does not exist" error. I am unsure what the difference between the latter two problems is. EDIT: Upon manually examining the contents of the directory I created, it seems that, as intended, I end up with only one image titled "sensorMap.png" at a time; it remains in the directory after the app closes, as expected. However, I still occasionally get the "File size: 0 bytes" message or the "File does not exist." message with no attached image, even though I see that the image DOES exist upon looking in directory afterwards. Other times, everything works just fine. It's rather bewildering.
In addition, there is an issue of the button which sends the email becoming unresponsive occasionally. Most of the time, it prompts the user to select an email client, as intended, but occasionally the button will LOOK as if clicked, but do nothing. When this happens, the logcat does not sense that the button was even clicked (I inserted a println statement to test it).
I am unsure of why my delete-before-download is not working flawlessly; the basic idea, at least, appears to be logically sound. Here is the code pertaining to my issue:
Code used to download file (in MainCountActivity.java):
//Function to download image given URL. Will use to attach image file to email.
public void downloadFile(String uRl) {
//delete existing file first so that only one sensorMap image exists in memory
//at any given time.
File file = new File(Environment.getExternalStorageDirectory()+"/SensorLocationImages");
File checkFile = new File(Environment.getExternalStorageDirectory()+"/SensorLocationImages/sensorMap.png");
if(checkFile.exists())
{
//debugging:
System.out.println("About to delete file!");
//deleteFiles(Environment.getExternalStorageDirectory()+"/SensorLocationImages");
checkFile.delete();
}
DownloadManager mgr = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(uRl);
DownloadManager.Request request = new DownloadManager.Request(
downloadUri);
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false).setTitle("Sensor Location Map")
.setDescription("Pinpointed is the location from which the log file was sent.")
.setDestinationInExternalPublicDir("/SensorLocationImages", "sensorMap.png");
mgr.enqueue(request);
}
public Activity getActivity() //I wasn't sure if this would work, but it did. Or at least appears to.
{ return this; }
Method to send email (in MainCountActivity.java):
public void sendEmail(String toAddress, String ccAddress, String bccAddress, String subject, String body, String attachmentMimeType) throws Exception{
try {
Intent emailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
emailIntent.setType(attachmentMimeType); //new
String sToAddress[] = { toAddress };
String sCCAddress[] = { ccAddress};
String sBCCAddress[] = { bccAddress };
emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
emailIntent.putExtra(Intent.EXTRA_EMAIL, sToAddress);
emailIntent.putExtra(android.content.Intent.EXTRA_CC, sCCAddress);
emailIntent.putExtra(android.content.Intent.EXTRA_BCC, sBCCAddress);
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
emailIntent.putExtra(Intent.EXTRA_TEXT, body);
//get URI of logfile
File tempFile = new File(Environment.getExternalStorageDirectory () + MainCountActivity.dirPath);
Uri uri = Uri.fromFile(tempFile);
//create URI arraylist and add first URI
ArrayList<Uri> uris = new ArrayList<Uri>();
uris.add(uri);
//get URI of map image and add to arraylist
//make sure it is there to attach
File file = new File(Environment.getExternalStorageDirectory()+"/SensorLocationImages");
do {
downloadFile(getMapLink());
//createDirectoryAndSaveFile(getBitmapFromURL(getMapLink()), "sensorMap.png");
} while (!file.exists());
uris.add(Uri.fromFile(new File(Environment
.getExternalStorageDirectory()
+ "/SensorLocationImages/sensorMap.png")));
//+ "/sdcard/SensorLocationImages/sensorMap.png")));
emailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
startActivity(emailIntent);
}
catch(Exception ex) {
ex.printStackTrace();
throw ex;
}
}
OnClick method, for my occasional button issue (In MaincountActivity.java):
public void onClick(View v){
switch(v.getId())
{
case R.id.textView1:
{
break;
}
case R.id.Reset:
{
//allowCounting will let the program know when to let it to count or not, depending if Start or Stop button are pressed.
logCount=0;
mCounter.setText("Total: 0");
mToggle.setChecked(false);
break;
}
/* case R.id.toggleButton:
{
break;
}*/
case R.id.SendEmail:
{
//for debugging purposes:
System.out.println("Email button being clicked!");
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
Toast.makeText(this, "GPS is enabled in your device", Toast.LENGTH_SHORT).show();
try {
sendEmail("","","","Sensor Log Info",getEmailBody(),"multipart/mixed");
} catch (Exception e) {
e.printStackTrace();
}
}
else
{
showGPSAlertForEmail();
}
break;
}
}
Basically, I really want to know why my delete-then-download method has not worked every time. Logcat errors have provided no insight. Thank you for your time.

Simple way to add contact photo to ImageView?

I'm having problems getting and setting a contact's image as a view's background, surprisingly there are few examples on how to do it. I'm trying to build something similar to the People app which displays big contact photos.
This is what I'm doing right now:
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.valueOf(id));
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
Bitmap bm = BitmapFactory.decodeStream(input);
Drawable d = new BitmapDrawable(bm);
button.setBackgroundDrawable(drawable);
This works however the URI it uses gets a thumbnail picture, so even if there is a big photo images looks very bad when scaled to fit the imageView. I know another method to get the URI that actually gets a big photo which is:
final Uri imageUri = Uri.parse(cur.getString(cur.getColumnIndex(ContactsContract.Contacts.PHOTO_URI)));
However I haven't managed to get it to the imageView, maybe the code above can be adapted to use the second uri. If you know how to use the second uri or if there is an easier way to get the contact image than through the URI please tell me. Any info will be thanked.
Good job in getting the URI. You're almost there. First of all consider using PHOTO_THUMBNAIL_URI instead of PHOTO_URI, as it may be what you need in terms of size.
Edit : FYI, PHOTO_THUMBNAIL_URI is available starting API 11. You can still use it conditionally.
If you want to use an external library, 'Android Universal Image Loader' is definitely what you are looking for, as starting from it's 1.7.1 version from a few days ago, it added support for content schemes and it is pretty smart, memory wise. It also has a lot of customization options.
Edit: this lib is already dead. Use Fresco instead.
If you'd rather be nicer to your final bundle size and write the code yourself,
You need to get and decode the input stream of that content; This should be done on a background thread. Check out this connivence method; You initialise it with your image view and the uri you got and start it when you want to load the ImageView.
private class ContactThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
private WeakReference<ImageView> imageViewWeakReference;
private Uri uri;
private String path;
private Context context;
public ContactThumbnailTask(ImageView imageView, Uri uri, Context context) {
this.uri = uri;
this.imageViewWeakReference = new WeakReference<ImageView>(imageView);
this.path = (String)imageViewWeakReference.get().getTag(); // to make sure we don't put the wrong image on callback
this.context = context;
}
#Override
protected Bitmap doInBackground(Void... params) {
InputStream is = null;
try {
is = context.getContentResolver().openInputStream(uri);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap image = null;
if (null!= is)
image= BitmapFactory.decodeStream(is);
return image;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewWeakReference != null && imageViewWeakReference.get() != null && ((String)imageViewWeakReference.get().getTag()).equals(path) && null != bitmap)
imageViewWeakReference.get().setImageBitmap(bitmap);
}
}
It is suggestion. First know one thing.
When you set a contacts image. First Android show the Cropping activity for that image. Like
****carefully see above image. Android crop the image as square shape. And store the square shape image as a Blob in contacts.(It is not individual image. It is blob.)
You get a square shape image for your image view from your coding. so top and bottom show black color only. Because your mobile in rectangle shape.****
If you want to show full screen image. Please set a big image to contacts through programmatically. Lot of examples available in internet.
All the best for your try. If you have any doubts. Please provide comments.
You can try using SmartImageView: http://loopj.com/android-smart-image-view/ extends imageview and also loads images asynchronously.
Use an external library to do that for you. Or browse the code and make something similar your own way.
Here's one I use on several of my own apps: UrlImageViewHelper
The code would go like this:
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.valueOf(id));
UrlImageViewHelper.setUrlDrawable(button, uri.toString(), R.drawable.dummy_contact_photo);
You can easily set the contact photo to the image view by using the following method.
public String getImageUriString(String phoneNumber)
{
ContentResolver resolver = context.getContentResolver();
Cursor names = resolver.query(
Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)),
null, null, null, null);
names.moveToFirst();
String name = "";
if(!names.isAfterLast())
{
name = names.getString(names.getColumnIndex(ContactsContract.PhoneLookup.PHOTO_URI));
}
else
{
name = null;
}
names.close();
return name;
}
public void setImageView(ImageView contactPhoto) {
String photoUriString = di.getImageUriString(contactNumber);
if(photoUriString != null) {
Uri photoUri = Uri.parse(photoUriString);
contactPhoto.setImageURI(photoUri);
} else {
contactPhoto.setImageResource(R.drawable.icon_contact);
}
}
From your class, set the image view with the uri getting from the above method.
To be able to do that you have to just add one last parameter preferHighres = true:
openContactPhotoInputStream (ContentResolver cr, Uri contactUri, boolean preferHighres)
If preferHighres is true and the contact has a higher resolution photo available, it is returned. If false, this function always tries to get the thumbnail
Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.valueOf(id));
InputStream input = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri, true);
All the images probably would have differnet sizes. In order to resize them I use next code:
Bitmap bm = BitmapFactory.decodeStream(input);
bm = Bitmap.createScaledBitmap(photo, contactImageWidth, contactImageheight, false);
Drawable d = new BitmapDrawable(getContext(), bm);
button.setBackgroundDrawable(d);

Categories