I am building a simple image gallery app for android. I want the users to be able to pick images from it when they want to add an image to an SMS, an email, a chat application ... I have used intent filters in order to make my app appear in the app chooser menu when a user wants to add an image :
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.OPENABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
<data android:mimeType="vnd.android.cursor.dir/image" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
<data android:mimeType="vnd.android.cursor.dir/image" />
</intent-filter>
<intent-filter>
<action android:name="android.media.action.IMAGE_CAPTURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Then the user is able to select an image, but I am looking for the best way to respond with it to the caller app.
I've been trying by storing the image as a temp file and sending the URI of that file
public void respondWithImage(Bitmap bitmap){
try {
//If needed create temp folder
File folder = new File(Environment.getExternalStorageDirectory() + "/temp/");
if (!folder.exists()) {
folder.mkdirs();
}
File nomediaFile = new File(folder, ".nomedia");
if (!nomediaFile.exists()) {
nomediaFile.createNewFile();
}
//Create temp image file
FileOutputStream out = new FileOutputStream(
Environment.getExternalStorageDirectory()
+ "/temp/temp.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
File bitmapFile = new File(
Environment.getExternalStorageDirectory()
+ "/temp/temp.png");
//Tell parent activity to respond with the image
if (bitmapFile.exists()) {
Intent localIntent = new Intent().setData(Uri
.fromFile(bitmapFile));
parentActivity.setResult(Activity.RESULT_OK, localIntent);
} else {
parentActivity.setResult(Activity.RESULT_CANCELED);
}
parentActivity.finish();
} catch (Exception e) {
e.printStackTrace();
Log.d("error", "Error writing data");
}
}
This works but I wonder what it would do if the phone has no sdcard. I can't try that option because i got a GS3 which apparently considers its own memory as an ext card (correct me if I'm wrong)
I have also tried to send back an URI which points to a drawable resource (PNG file) from within my app, (it wouldnt be a problem in my case to have images in app resources) but it makes the calling app (MMS) crash and I don't catch the error in debugger.
What is the correct way to do that?
This works but I wonder what it would do if the phone has no sdcard
You are not using an "sdcard".
I can't try that option because i got a GS3 which apparently considers its own memory as an ext card (correct me if I'm wrong)
External storage normally is on-board flash, typically on the same partition that internal storage resides upon. While the documentation for external storage is not great, you may wish to review it.
I have also tried to send back an URI which points to a drawable resource (PNG file) from within my app... but it makes the calling app (MMS) crash and I don't catch the error in debugger.
You will not catch a crash from some third-party app in the debugger, as you are debugging your app, not the third-party app. LogCat may contain a stack trace, though.
What is the correct way to do that?
Use FileProvider
, or perhaps my StreamProvider
, to offer a ContentProvider
for serving up your images. Your Uri
would then be a content://
Uri
. This should be supported by most apps, as images routinely come from content providers (e.g., email attachments).