In short:
My app should let the user take and display photos using the standard apps.
The photos should not show up in the Gallery.
The photos should be removed when the app is de-installed.
What I got so far:
Since I want to use the device's default camera app, I need to use a shareable place for the files.
I tried using 'ExternalFilesDir' with a 'Manifest/xml/provider' contructed Uri in the calling
intent. This seams to work with the camera app:
private String mImagePath;
private void takePhoto(){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) == null) return;
String filename="Image" + System.currentTimeMillis();
File dir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File file =null;
try{
file = File.createTempFile(filename,".jpg", dir);
}catch(Exception ex){
ex.printStackTrace();
}
if (file == null) return;
mImagePath =file.getAbsolutePath();
Uri uri = FileProvider.getUriForFile(this,getApplicationContext().getPackageName()+".provider", file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, requestcode);
}
This part seams to work (due to my 'competence' I cannot check the folder since the Android Studio's Device File Eplorer does not let me, grrh!).
But when I try to display the images, all the standard apps (Gallery, Foto etc.) throw an 'access denied' error message.
private void displayPhoto{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri contentUri = FileProvider.getUriForFile(this,getApplicationContext().getPackageName()+".provider", new File(mImagePath));
intent.setDataAndType(contentUri, "image/*");
startActivity(intent);
}
My questions are:
Why can the camera app store a file in ExternalFilesDir but the
displaying app cannot read it from there?
-or-
Is there something wrong with my code?
Can my app somehow grant access to the displaying app?
What other concept could I use to achieve my targets?
How can I browse the content of ExternalFilesDir within Android
Studio or another tool?
I do not want to write my own displaying code since the user is familliar with the standard app.
I need to use minSDKVersion 22.
Thanks for helping me here!
Meanwhile, after hours and hours, I found the reason why Gallery or other apps show the 'access denied' error:
Im addition to the uri the caller app has to set the 'FLAG_GRANT_READ_URI_PERMISSION' flag in the calling intent. Like this:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(mycontenturi, "image/*");
intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
Also I found that the only entries in the fileprovider xml which work are:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="my_images" path="Pictures/" />
<external-files-path name="my_images" path="." />
<external-files-path name="camera_image" path="."/>
<external-files-path name="camera_image" path="Pictures/"/>
</paths>
Funny enough: when path is "." it creates a Pictures subdir and when it says "Pictures/" it doesn't.
Related
I'm trying to update the app which will not be published to the play store since it is for internal use, I've been able to download the file but while launching an intent to install it getting "Error parsing package"
I've tried saving the file in the public directory as mentioned in few links.
I've used FileProvider for getting the URI since the target device is 8.x.
I've checked the apk by installing it manually from the file manager app and also adb to make sure there is no problem with the apk.
I've tried multiple intent actions for installing the app.
All the permissions are given.
--Permissions:
android:name="android.permission.INTERNET"
android:name="android.permission.ACCESS_NETWORK_STATE"
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:name="android.permission.REQUEST_INSTALL_PACKAGES"
--Intent codes that I've tired:
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); intent.setData(FileProvider.getUriForFile(StandardListActivity.this, BuildConfig.APPLICATION_ID+".authorityStr",localFile));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
startActivity(intent);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(getPackageName().toString())); intent.setDataAndType(FileProvider.getUriForFile(StandardListActivity.this, BuildConfig.APPLICATION_ID+".authorityStr"
,localFile), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Intent installIntent = new Intent(Intent.ACTION_VIEW); installIntent.setDataAndType(FileProvider.getUriForFile(StandardListActivity.this,BuildConfig.APPLICATION_ID+".authorityStr",localFile), "application/vnd.android.package-archive");
installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(installIntent);
--Creating a local file for storage:
File rootPath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "/blee");
if (!rootPath.exists()) {
rootPath.mkdirs();
}
final File localFile = new File(rootPath, "test2.apk");
Want to know if there is anything else I can try and please do not redirect me to different threads as probably I've already tried that.
While sharing image URI to other sharing is getting failed. So I want a solution on how to share my app images to other app using bluetooth, whatsapp etc.
Here is my code:
ArrayList <Uri> imageUri = new ArrayList<>();
for (int i = 0; i < urimodel.size(); i++) {
Uri model_uri = urimodel.get(i); //getting uri from here
imageUri.add(model_uri);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUri);
shareIntent.setType("image/*");
context.startActivity(Intent.createChooser(shareIntent, "Share images to.."));
}
My suggestion first save image which u want to share then pass uri
Ref : Share Image with Other Apps
Try something Like this
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
shareIntent.setType("image/*");
// For a file in shared storage. For data in private storage, use a ContentProvider.
Uri uri = Uri.fromFile(getFileStreamPath(pathToImage));
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(shareIntent)
If you want to share it via the assets folder, you'll have to use a ContentProvider. See this answer on how to do so:
https://stackoverflow.com/a/7177103/1369222
OR
Add File Provider in Android Manifest
<provider
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider_paths"/>
file_provider_paths.xml
<paths>
<cache-path name="cache" path="/" />
<files-path name=”files” path=”/” />
</paths>
See That How to use support FileProvider for sharing content to other apps?
this must be because your firebase storage setting didn't allow to read and write without auth
just go to to storage>rules and change the rules with this
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read;
allow write: if request.auth != null;
}
}
}
this will allow everyone can read your image
Warning reading and writing the storage database also count and you need to pay cost to remain it work after certain limit. check pricing here
I tried below code it is working upto Marshmallow it's not working in Nougat..can any one help me how to solve this...
I have a Excelfile in my internal storage...i what open excelfile when button clicked if wps is not install i am redirected to Playstore to Install wps...
I am getting error like:
android.os.FileUriExposedException:
file:///storage/emulated/0/Test%20Distributor%20Report.xlsx exposed
beyond app through Intent.getData()
void openExcel()
{
Intent intent = new Intent(Intent.ACTION_VIEW);
/*vnd.ms-excel*/ /*application/vnd.openxmlformats-officedocument.spreadsheetml.sheet*/
intent.setDataAndType(Uri.fromFile(file),"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
try {
context.startActivity(intent);
}catch (Exception e)
{
Toast.makeText(context,"Please Install WPS Application To View Reports",Toast.LENGTH_LONG).show();
Intent viewIntent =
new Intent("android.intent.action.VIEW",
Uri.parse("https://play.google.com/store/apps/details?id=cn.wps.moffice_eng&hl=en"));
context.startActivity(viewIntent);
Log.d("printexeption",""+e.toString());
}
}
If your targetSdkVersion is 24 or higher, we have to use FileProvider class to give access to the particular file or folder to make them accessible for other apps. We create our own class inheriting FileProvider in order to make sure our FileProvider doesn't conflict with FileProviders declared in imported dependencies as described here.
Steps to replace file:// uri with content:// uri:
add a class extending FileProvider
public class GenericFileProvider extends FileProvider {
}
add a FileProvider tag in AndroidManifest.xml under tag. Specify an unique authority for the android:authorities attribute to avoid conflicts, imported dependencies might specify ${applicationId}.provider and other commonly used authorities.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
...
<application
...
<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>
</application>
</manifest>
then create a provider_paths.xml file in xml folder under res folder. Folder may be needed to create 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 xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
The final step is to change the line of code below in
Use the below mentioned code to open excel file :
File file = new File(Environment.getExternalStorageDirectory()+ "/filepath/" + filename);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),"application/vnd.ms-excel");
startActivity(intent);
Edit: If using an intent to make the system open your file, you may need to add the following line of code:
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Hope this will help...:)
Please refer, full code and solution has been explained here.
If your targetSdkVersion is 24 or higher, you can not use file: Uri values in Intents on Android 7.0+ devices.
Your choices are:
Drop your targetSdkVersion to 23 or lower, or
Put your content on internal storage, then use FileProvider to make it available selectively to other apps
For example:
Intent i=new Intent(Intent.ACTION_VIEW, FileProvider.getUriForFile(this, AUTHORITY, f));
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(i);
This question already has answers here:
Android ACTION_SEND event: "messaging failed to upload attachment"
(2 answers)
Closed 5 years ago.
I am trying to create a Sharing Intent for an Android App to share images to other apps. However, I'm getting this really weird result when implementing this feature.
I have a share button that when I click on the button, it runs the following method:
private void shareIntent() {
Uri currUri = Uri.parse(data.get(pos).getUrl());
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setAction(Intent.ACTION_SEND);
sharingIntent.putExtra(Intent.EXTRA_STREAM, currUri);
sharingIntent.setType("image/jpg");
startActivity(Intent.createChooser(sharingIntent, getResources().getText(R.string.share_to)));
}
data.get(pos).getUrl() returns the URL of a custom class I made that implements Parcelable, and when printing it out, it returns a directory like the following: "/storage/emulated/0/Pictures/primitive/Primitive-79538313.jpg"
The intent works at first, opening the sharing menu. However, when I click on most applications, it either crashes the application or it gives an error... except with Google Photos, which uploads the photo properly to the gallery.
Firstly, I'm wondering what I'm doing wrong to cause this issue in the other apps. Also, I'd like to know if someone has an explanation as to why only Google Photos allows the sharing feature to work, while many of the other apps I've tested do not.
For reference, here are some examples I've run with the sharing intent. When I try to share the image, it crashes Hangouts. It gives a "failed to load image" error message in Snapchat, "Unable to share file" in Slack and Gmail, "Upload was unsuccessful" in Drive, "Messenger was unable to process the file" in, well, Messenger, and "Couldn't load image" in GroupMe. It doesn't load the image in Facebook but doesn't crash nor give an error.
Thank you for any help or feedback you can provide!
EDIT:
This seemed to work without trying to get around App Permissions:
private void shareIntent() {
File imageFile = new File(data.get(pos).getUrl());
Uri uriToImage = FileProvider.getUriForFile(
this, BuildConfig.APPLICATION_ID + ".provider", imageFile);
Intent shareIntent = ShareCompat.IntentBuilder.from(DetailActivity.this)
.setStream(uriToImage)
.getIntent();
shareIntent.setData(uriToImage);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, "Share image"));
}
Thank you to everyone that responded!
Change your code to this
private void shareIntent() {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/jepg");
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://"+data.get(pos).getUrl()));
startActivity(Intent.createChooser(shareIntent, "Share image"));
}
Add this code in your activity onCreate()
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
I'm trying to pick a file via an Intent.
What I tryed till now is this:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, FILE_SELECT_CODE);
But with this, I can only pic Photos with the galery app.
My goal is to pic ANY file via the standard file manager of Android/Samsung.
This didn't work either:
String manufactures = android.os.Build.MANUFACTURER;
if(manufactures.equalsIgnoreCase("samsung"))
{
Intent intent = new Intent("com.sec.android.app.myfiles.PICK_DATA");
intent.putExtra("CONTENT_TYPE", "*/*");
startActivityForResult(intent, FILE_SELECT_CODE);
}
Thx for your help!
My goal is to pic ANY file via the standard file manager of Android/Samsung.
Android does not have a "standard file manager".
If your minSdkVersion is 19 or higher, you are welcome to use the Storage Access Framework (e.g., ACTION_OPEN_DOCUMENT), which is the closest thing that Android now has to a "standard file manager".
Otherwise, you are limited to whatever ACTION_GET_CONTENT-supporting apps that the user has installed, or creating your own file-selection UI, or using one of many existing libraries for selecting files.