I'm new to android and having a headache trying to do this scenario:
I'm creating a backup of my database, which is exists in a path like this:
String dbPath = "data/data/" + c.getPackageName() + "/databases/" + DatabaseHelper.DATABASE_NAME;
I'm copying current database file to another in same directory with a custom extension, something like this:
String backupName = "data/data/" + a.getBaseContext().getPackageName() + "/databases/MyDB_" + MyTools.GenerateDateNow() + ".mydb";
then i use a recycler view and an adapter to loop through files inside the folder, and get my custom created files
i also have a button inside the recycler view, which will restore the created backup.
everything up till now is alright and works fine.
what i want to do next is the problem:
i need to share these backups with other people ( if user decides to ), and to do that, i have used Intents to send a user selected backup file to all apps which work with files ( gmail, whatsapp, ...):
holder.btnShare.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
Intent myIntent = new Intent(Intent.ACTION_SEND);
myIntent.setType("file/*");
Uri fileUri = Uri.fromFile(file);
myIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
Intent chooserIntent = Intent.createChooser(myIntent, "Share With...");
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
chooserIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(chooserIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
});
the selected file will be picked and sent to the chooserIntent, but it seems like the chooserIntent has no permission to access it, i guess it's something simple that I'm missing
Related
I'm building an app that allows the user to save the bitmap or share it without saving it. The 2nd functionality doesn't quite work. I understand that the app needs to save the file to the device before sharing it on a social media app so my idea was, immediately after the file was successfully shared, to automatically delete the file from the device. I've build a delete method trying 2 different approaches and neither have worked:
First approach:
public void deleteFile(String path){
File file = new File(path);
try {
file.getCanonicalFile().delete();
} catch (IOException e) {
e.printStackTrace();
}
}
Second approach:
public void deleteFile(String path){
File file = new File(path);
boolean deleted = file.delete();
}
And I'm calling deleteFile(String) from the sharing method:
public void shareMeme(Bitmap bitmap) {
String path = MediaStore.Images.Media.insertImage(Objects.requireNonNull(getContext()).getContentResolver(), bitmap, "Meme", null);
Uri uri = Uri.parse(path);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
share.putExtra(Intent.EXTRA_TEXT, "This is my Meme");
getContext().startActivity(Intent.createChooser(share, "Share Your Meme!"));
deleteFile(path);
}
With respect to your stated problem, insertImage() returns a string representation of a Uri. That Uri is not a file. Calling getPath() on it is pointless, and you cannot delete anything based on that path.
More broadly, if your intention is to delete the content right away:
Do not put it in the MediaStore
Do not share it, as you will be deleting it before the other app has a chance to do anything with it
If you want to share it, but then delete it:
Do not put it in the MediaStore
Delete it the next day, or in a few hours, or something, as you have no good way of knowing when the other app is done with the content
To share an image with another app without using the MediaStore:
Save the image to a file in getCacheDir() (call that on a Context, such as an Activity or Service)
Use FileProvider to make that file available to other apps
Beyond that:
Do not use wildcard MIME types in ACTION_SEND. You are the one who is supplying the content to send. You know the actual MIME type. Use it.
Note that there is no requirement for an ACTION_SEND activity to honor both EXTRA_TEXT and EXTRA_STREAM. Most seem to do so, but that behavior is outside of the ACTION_SEND specification.
Note that insertImage() is deprecated on Android Q.
First, you need to check if your file exists, (maybe you set the wrong path?). Then delete the file
File file = new File(path);
if (file.exists()){
if (file.delete()) {
Toast.makeText(this, "file Deleted :" + path, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "file not Deleted :" + path, Toast.LENGTH_SHORT).show();
}
}
When sharing a file (text file in this case), is it possible to specify an attribute that limits the number of apps to select?
For example, I run an ACTION_SEND by Intent to share a text file through FileProvider interposed. Android then proposes 10 or 12 apps, whereas only one or two manage to exploit the text file: Gmail, to send an email, X-plore or Total Commander to copy it, but not Chomp to send an sms with attachment, nor such or such notepad...
For example we would need an attribute type: "mail" + "storage" and what else!?
My code, to illustrate and that works well on an external file:
File file = new File(Environment.getExternalStorageDirectory() +
File.separator + filepath, filename);
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/*");
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {" "});
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, »Bla « bla bla);
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,"[" +
file.getName() + "]");
Uri fileUri = FileProvider.getUriForFile(this
, getString(R.string.fileProvAuthorities)
, file);
emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
startActivity(Intent.createChooser(emailIntent, "To share"));
There's nothing like that. But you could create your own chooser showing only the apps you want.
You can do that easily via Flipboard BottomSheet library
Here is a sample:
First, create a string array includes the package names of apps to be shared with, into your strings.xml file like that:
<string-array name="share_apps">
<item>com.facebook.katana</item>
<item>com.facebook.orca</item>
<item>com.twitter.android</item>
<item>com.whatsapp</item>
<item>com.google.android.apps.messaging</item>
<item>com.google.android.talk</item>
<item>com.google.android.gm</item>
<item>com.google.android.apps.plus</item>
<item>com.pinterest</item>
<item>com.instagram.android</item>
<item>com.android.email</item>
<item>com.microsoft.office.outlook</item>
<item>com.yahoo.mobile.client.android.mail</item>
<item>ru.yandex.mail</item>
</string-array>
You can add or remove whatever you want in the list. Then, you can use the bottomsheet like below
IntentPickerSheetView intentPickerSheet = new IntentPickerSheetView(MainActivity.this, shareIntent, "Share with...", new IntentPickerSheetView.OnIntentPickedListener() {
#Override
public void onIntentPicked(IntentPickerSheetView.ActivityInfo activityInfo) {
bottomSheet.dismissSheet();
startActivity(activityInfo.getConcreteIntent(shareIntent));
}
});
// Filter out built in sharing options such as bluetooth and beam.
intentPickerSheet.setFilter(new IntentPickerSheetView.Filter() {
#Override
public boolean include(IntentPickerSheetView.ActivityInfo info) {
String packageName = info.componentName.getPackageName();
ArrayList<String> apps = new ArrayList<String>(Arrays.asList(getResources().getStringArray(R.array.share_apps)));
return apps.contains(new String(packageName));
}
});
// Sort activities in reverse order for no good reason
intentPickerSheet.setSortMethod(new Comparator<IntentPickerSheetView.ActivityInfo>() {
#Override
public int compare(IntentPickerSheetView.ActivityInfo lhs, IntentPickerSheetView.ActivityInfo rhs) {
return rhs.label.compareTo(lhs.label);
}
});
bottomSheet.showWithSheetView(intentPickerSheet);
Recently I am developing a file sharing application and I created a GridView, where the downloaded files are being shown. From this View, I would like to be able to open the default application through an intent, to open the whole file. Currently I am testing the app with only image files. All the files are downloaded to the external public directory this way:
File externalFolder = new File(Environment.getExternalStorageDirectory(), "My application");
if(!externalFolder.exists()){
externalFolder.mkdir();
}
...
File folder = new File(externalFolder, "Images");
if(!folder.exists()){
folder.mkdir();
}
...
String filename = folder.getAbsolutePath() + "/" + fileToDownload.getName() + "." + fileToDownload.getExtension();
FileOutputStream fos = new FileOutputStream(filename);
When the file is downloaded, I scan it with MediaScannerConnection.scanFile. The scan is successful, the picture is visible among other files in Photos app.
After the file is downloaded, I am able to extract a thumbnail in the adapter of the GridView, so I surely have a valid path to the file.
And where the fun begins: I tried to set an onClickListener to the GridView items in the adapter to be able to open the picture in Photos app this way:
listItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
if(new File(current.getPath()).exists()){
Log.e("path", "valid");
}else{
Log.e("path", "invalid");
}
Log.e("path", Uri.parse("content://"+current.getPath()).toString());
intent.setDataAndType(Uri.parse("content://"+current.getPath()), "image/*");
getContext().startActivity(intent);
}
});
The Intent is created successfully, I get the following in the log:
E/path: valid
E/path: content:///storage/emulated/0/My application/Images/best_picture_ever.jpeg
I have the option to choose among apps to open. When I select the app, it fails to open the image, like when it does not exist. All the 5 applications.
I tested this on my device with Oreo, and on two emulated devices with Nougat and Lollipop, all of them behaves the same way.
What am I doing wrong?
What am I doing wrong?
You are not creating a valid Uri. You cannot put content:// in front of arbitrary things and have a useful Uri, any more than you can put https:// in front of arbitrary things and have a usable URL.
Use FileProvider to serve up this file.
In my application when i download an image ,it downloads but doesn't show in gallery image whats the problem?
i tried to use mediaScanner but it doesn't work for me.
thanks.
Storage sss = SimpleStorage.getExternalStorage();
String path = "myApp" + "/" +"qaiqai21";
sss.createDirectory(path);
try {
lastFileName = "test" + "_TESTINT_" +
randomString(3) + ".jpg";
sss.createFile(path, lastFileName,
IOUtil.readFile(response));
} catch (IOException e) {
}
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
}
});
Call below code after successful download
/**
* Add captured image to the gallery
*
* #param context,uri
*/
public static void addToGallery(Context context, Uri uri) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(uri);
context.sendBroadcast(intent);
}
first of all you need to know if you device api >=23 or not , if yes so give it write/read external storage in run time ,
step two in code that download file in OutputStream output = new FileOutputStream(dataDirPath); dataDirPath must be the gallery directory dataDirPath= context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
so if your file not in Environment.DIRECTORY_PICTURES it will not save in gallery
I'm working on a program which needs to show list file in ListView. I got this list with path_of_files. But this is what i want to ask: when i clicked on an item, how can user open it? I think i want a popup let user choose which program user want to open it.
For example: I have a path: /sdcard/file.xls. When user clicked in, a popup shows some application like: Microsoft Excel, Google Spreadsheet (I only want to work with xls - and it only works with it, still ok). How can i do it?
File sdCardRoot = Environment.getExternalStorageDirectory();
File yourDir = new File(sdCardRoot, "directory");
for (File f : yourDir.listFiles()) {
if (f.isFile()) {
String name = f.getName();
Long lastModified = f.lastModified();
if (name.toLowerCase().contains(".xls"))
fileObjList.add(new FileObj(0,name,lastModified));
}
}
This is my code to get filename and file path.
First , set a listener to your listView Items . And inside the handler callback you can do something likebelow to open up excels :
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/vnd.ms-excel");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
Toast.makeText(context, "No Application Available to View Excel", Toast.LENGTH_SHORT).show();
}