Sharing failed while sharing Firebase image URI to other apps? - java

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

Related

Concerns about the FILES AND MEDIA PERMISSIONS on Android as a developer

I'm developing an app that saves data into a database, I'm trying to backup and restore that database which I am able to do, my issue is with the "ominous" permmission popup on API30+
Allow management of all files
Allow this app to access modify and delete files on your device.....
Allow this app to access, modify and delete files on the device or any connected storage devices? this app may access files without asking you.
I'm not trying to do any of these things, I just want permission to do the backup/restore thing
here's my code for requesting permission:
private void requestStoragePermissionExport(){
if( (Build.VERSION.SDK_INT >= 30 )){
try {
Intent intent = new Intent(Manifest.permission.MANAGE_EXTERNAL_STORAGE);
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse(String.format("package:%s",getApplicationContext().getPackageName())));
startActivityForResult(intent, 2296);
} catch (Exception e) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
startActivityForResult(intent, 2296);
}
}else{
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE}, BACKUP_CODE);
}
}
is there a better way to handle this?
Google is restricting use of broad file permissions such as MANAGE_EXTERNAL_STORAGE. You can use Storage Access Framework to gain limited access to certain files or directories.
// Request code for selecting a PDF document.
const val PICK_PDF_FILE = 2
fun openFile(pickerInitialUri: Uri) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/pdf"
// Optionally, specify a URI for the file that should appear in the
// system file picker when it loads.
putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
}
startActivityForResult(intent, PICK_PDF_FILE)
}
Or if you want to access an entire directory;
fun openDirectory(pickerInitialUri: Uri) {
// Choose a directory using the system's file picker.
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
// Optionally, specify a URI for the directory that should be opened in
// the system file picker when it loads.
putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri)
}
startActivityForResult(intent, your-request-code)
}
There are some restrictions to which paths you can access. You can read more about it here
https://developer.android.com/training/data-storage/shared/documents-files
You can just backup your db file to the public Documents directory.
No need for the permissions you mentioned.
Alright so, after a bit of research I found the best solution for myself is as follows:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + File.separator + "foldername"
this doesn't require permissions and works on below and above API 30

Storage sharing with standard apps concept

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.

Trying to include Zxing barcode scanner library into my Android project modifying the intent name

I am trying to read custom qr codes with my app using Zxing.
I have added the library to my code. Now I can call the Zxing scan intent and it starts the camera, reads the qr code.
But I also want to change the intent string to prevent conflict with the original Barcode scanner app installed on the phone.
So I changed the intent filter in manifest file as:
from:
<action android:name="com.google.zxing.client.android.SCAN"/>
to:
<action android:name="com.google.zxing.client.android.SCANX"/>
And from my activity I call :
if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, 1);
} else {
Toast.makeText(ctx, "test1",Toast.LENGTH_LONG).show();
Intent intent = new Intent("com.google.zxing.client.android.SCANX");
intent.putExtra("SCAN_FORMATS", "QR_CODE_MODE");
startActivityForResult(intent, IntentIntegrator.REQUEST_CODE);
//startActivityForResult(intent, 0);
}
However, it stays at the result page with options like "share via email", "share via sms" , "search" etc. I don't want to see this page, I want to get the code directly to the result.
And if I restore the intent string back to original:
<action android:name="com.google.zxing.client.android.SCAN"/>
it works.
But I really want to prevent conflict and the necessity for user to choose scanning app. How can I achieve this ?
thanks.

How to open wps office in my application Nougat?

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);

Open image (InternalStorage) with android default application using FileProvider

I have a picture stored in my internal application storage, and I want to open it with android default application (gallery or any other).
So I'm using a FileProvider, my code works fine on android 4.3, but on some versions (2.3.6 for example), it doesn't work, the application open itself but then blackscreen, nothing.
My app needs to be API-10 compatible
I read many topics relating this problem, nothing seems to fix it. The code is probably not wrong since it works on 4.3...
Any thought?
My code to launch the activity :
File file = getMyFile();
Uri contentUri = FileProvider.getUriForFile(getContext(), <full-path-to-my-activity>, file);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(contentUri, "image/*");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent = Intent.createChooser(intent, "Open with");
startActivity(intent);
in my manifest :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="<full-path-to-my-activity>"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider"/>
</provider>
my provider.xml :
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="pictures"
path=""/>
</paths>

Categories