I try to share a picture from my SD card.
Class MainActivity.java
Intent shareIntent = new Intent(Intent.ACTION_SEND);
File baseDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
String fileName = "/cats.jpg";
File file = new File(baseDir + fileName);
Uri uri = Uri.fromFile(file);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(shareIntent.createChooser(shareIntent, "Send Picture"));
I add to my Manifest.xml:
uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
The image "cats" is in
MySmartphone\Card\DCIM\cats.jpg
When I start my App, I can choose an application to share my picture. But when I open one, it cannot send or open the image.I got often a toast "not supported" or "error to share picture". I think my uri or file is wrong, but I cannot find my mistake. I have no problem to send text.
My uri:
file:///data/user/0/com.example.jana.showpicture/files/cats.jpg
My file: /storage/emulated/0/cats.jpg
Probably you are building for Android API 24 and above. Since API 24 a new kind of security was added. See:
https://developer.android.com/about/versions/nougat/android-7.0-changes.html#perm
You now need to do a bit more, add this in your AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.jana.showpicture.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
/res/xml/provider_paths.xml:
<paths>
<external-path
name="external_files"
path="." />
</paths>
And Java:
Uri uri = FileProvider.getUriForFile(activity,"com.example.jana.showpicture.provider",
file);
shareIntent .setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
Intent.FLAG_GRANT_READ_URI_PERMISSION);
Related
I have image list and I want to share image that selected.To do, I have used FileProvider. I'm running app on Android 10. Also I have tried without shareIntent(Intent.EXTRA_STREAM,uri), then app opening only share via dialogs.After not sharing anything just returning the app.
in AndroidManifest.xml;
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider_paths" />
</provider>
in paths;
<paths>
<files-path
name="files"
path="/" />
<cache-path
name="cache"
path="/" />
here is the how I used and start intent,
int pos = getAdapterPosition();
File imageFile = new File(imageQuotes.get(pos).getPath());
Uri uri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".provider", imageFile);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setDataAndType(uri,"image/*");
shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
mContext.startActivity(shareIntent);
When run the app,after I have choosed WhatsApp for ie. My image file sent as a BIN file and not has image preview on whatsapp.
uri is not null and is content://com.scoto.partestestapplication.provider/files/SavedImageQuotes/Partes_1601815401590
I have a PDF file I am trying to share through Intent.ACTION_SEND. Though when I click on one of the options (gmail, google drive, etc). It says "Request contains no data."
**Updated Code Below
case R.id.share_item:
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("application/pdf");
shareIntent.putExtra(Intent.EXTRA_STREAM, displayedFile.getAbsolutePath());
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share PDF using.."));
return true;
}
I assume the issue must be with my putExtra? That being said the URL for my file definitely works because I can successfully use that path for printing PDFs.
Edit:
I've Updated my code a smidge.
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("application/pdf");
Uri uri = Uri.parse(displayedFile.getAbsolutePath());
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share PDF using.."));
This gets me "file format not accepted" from Whatsapp and "Unable to attach file" from Gmail.
Wondering if the issue is with calling from Internal Storage or not using FileProvider.
Edit 2:
Trying to add this code but I am getting a crash
Uri outputPdfUri = FileProvider.getUriForFile(this,
PdfViewActivity.this.getPackageName() + ".provider", sharingFile);
I've also added this to my Manifest and file_paths
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.androidextensiontest.files"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
Alright sharing my own answer because I spent hours on this.
case R.id.share_item:
//these policy guidlines do not follow google Guidelines, recommended to change system
//https://stackoverflow.com/questions/48117511/exposed-beyond-app-through-clipdata-item-geturi
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("application/pdf");
File sharingFile = new File(displayedFile.getPath());
Uri outputPdfUri = FileProvider.getUriForFile(this, PdfViewActivity.this.getPackageName() + ".provider", displayedFile);
shareIntent.putExtra(Intent.EXTRA_STREAM, outputPdfUri);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//Write Permission might not be necessary
shareIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share PDF using.."));
return true;
}
This share_item button pulls from my saved file in Internal Storage. They key was getting the manifest and xml file written correctly.
Make sure this goes within your application tags in your AndroidManifest.xml - As well as notice I am using Androidx, change that line accordingly. I also never figured out the android:authorities line, but I found the filled in answer was the most common on Github.
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
Lastly file_paths.xml - create an xml package inside your red folder, and post this code. For some reason other code was what made my file sharing not work.
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="projection" path="." />
</paths>
Issue: What happens is after sharing the video when i launch the app to check the shared video it shows me error of "Unable to import" and "The video is no longer available".
Android Version: Oreo(8.0)
Code: I am trying with the following code to share videos with other apps using intent:
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("video/*");
share.putExtra(Intent.EXTRA_SUBJECT, "abc");
share.putExtra(Intent.EXTRA_TITLE, "abcd");
File imageFileToShare = new File(Environment.getExternalStorageDirectory() + "/mygallery/" + "airp.mp4");
Uri uri = FileProvider.getUriForFile(Main2Activity.this, "abc.dcf.fileprovider", imageFileToShare);
share.putExtra(Intent.EXTRA_STREAM, uri);
share.setPackage("com.abc.in");
startActivity(Intent.createChooser(share, "Message"));
The above code is working fine to share Images but its not working to share videos.
What i have tried: I have tried by sharing various file types like 3gp, mkv, mp4 but nothing is working out and I have also went through various similar questions but no solution is working in case of videos.
Please help me with this issue and also if there is any alternate way to do so?
You can add this to your OnCreate
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
If that doesn't work for you,
Add Provider to Manifest by doing this
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
Remember to use android:name="androidx.core.content.FileProvider" if you're using androidx
Create a file in xml directory (res/xml) and name provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Replace
Uri uri = FileProvider.getUriForFile(Main2Activity.this, "abc.dcf.fileprovider", imageFileToShare);
with this
Uri uri = FileProvider.getUriForFile(Main2Activity.this, BuildConfig.APPLICATION_ID + ".provider",imageFileToShare);
String sharePath = dataSavingModels.get(pos).getPathOfRecording();
Uri uri = Uri.parse(sharePath);
Intent share = new Intent(Intent.ACTION_SEND);
share.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
share.setType("audio/*");
share.putExtra(Intent.EXTRA_TEXT, dataSavingModels.get(pos).getTextSaved());
share.putExtra(Intent.EXTRA_STREAM, uri);
context.startActivity(Intent.createChooser(share, "Share Sound File"));
This is the code that I am using to send an audio file, it only sends audio files to WhatsApp, and no other app like Messenger, or Telegram or KakaoTalk
We create our own class inheriting FileProvider in order to make sure our FileProvider doesn't conflict with FileProviders declared in imported dependencies. First create class with name GenericFileProvider like this:
import android.support.v4.content.FileProvider;
public class GenericFileProvider extends FileProvider {
}
Then create provider_paths.xml inside res/xml folder. Folder may be needed to created if it doesn't exist. The content of the file is shown below. It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files.:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
</paths>
Now in manifest inside application tag, add this lines:
<provider
android:name=".GenericFileProvider"
android:authorities="${applicationId}.my.package.name.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
Then Try this code:
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/*");
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
share.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".my.package.name.provider", new File(Objects.requireNonNull(sharePath))));
startActivity(Intent.createChooser(share, "Share Sound File"));
I want to share multiple image from application package directory. My files locate in following path as like. /data/data/com.example. Now i can get images path. But not attach any images to sharing application. as like whats app, Message and Facebook etc. I have implemented permition in manifest file. See below my try.
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(saveList.get(0).toString())));
startActivity(Intent.createChooser(intent, "Share"));
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND_MULTIPLE);
intent.putExtra(Intent.EXTRA_SUBJECT, "Here are some files.");
intent.setType("image/*"); /* This example is sharing jpeg images. */
ArrayList<Uri> files = new ArrayList<Uri>();
for(String path : saveList /* List of the files you want to send */) {
File file = new File(path);
Uri uri = Uri.fromFile(file);
files.add(uri);
}
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files);
startActivity(intent);
Implemented permission is below.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
It is compatible with scoped storage. So don't need any storage permission.
fun shareFile(){
var intentBuilder: ShareCompat.IntentBuilder
intentBuilder = ShareCompat.IntentBuilder.from(this)
.setType("image/jpg")
intentBuilder.addStream(FileProvider.getUriForFile(this.baseContext!!
, getString(R.string.package), File(path)))
val intent = intentBuilder.intent.setAction(Intent.ACTION_SEND).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivity(Intent.createChooser(intent, "Send to "))
}
In Manifest
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
Create a xml file
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path path="/" name="allfiles" />
<external-path path="/" name="externalfiles" />
<root-path name="external_files" path="/storage/" />
</paths>
First, Uri.fromFile() will not work in your case, because third-party apps have no access to your internal storage.
Second, using a file: Uri, such as from Uri.fromFile(), appears as though it will be banned in the next version of Android.
Instead, you need to use some sort of ContentProvider, such as FileProvider, to make the files available to third-party apps. This is covered in the documentation.