I'm using following code to open a gallery inside of my app
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, FIND_RESULT);
Is it possible to limit a list of images to only show images taken by camera? Viewing Gallery on my 2.1 system, images are grouped so there has to be a parameter that defines to which folder it belongs.
Checking the MediaStore.Images.ImageColumns I did not a find any column that would define such thing.
Could I be wrong? Because if I could create a query to filter by folder and create my own gallery view, then my problem would be solved.
You just need to implement MediaScannerConnectionClient in your activity and after that you have to give the exact path of one of the file inside that folder name here as SCAN_PATH and it will scan all the files containing in that folder and open it inside built in gallery. So just give the name of you folder and you will get all the files inside including video. If you want to open only images change FILE_TYPE="image/*"
public class SlideShow extends Activity implements MediaScannerConnectionClient {
public String[] allFiles;
private String SCAN_PATH ;
private static final String FILE_TYPE = "*/*";
private MediaScannerConnection conn;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
File folder = new File("/sdcard/yourfoldername/");
allFiles = folder.list();
SCAN_PATH=Environment.getExternalStorageDirectory().toString()+"/yourfoldername/"+allFiles[0];
Button scanBtn = (Button) findViewById(R.id.scanBtn);
scanBtn.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
startScan();
}
});
}
private void startScan()
{
if(conn!=null)
{
conn.disconnect();
}
conn = new MediaScannerConnection(this, this);
conn.connect();
}
public void onMediaScannerConnected()
{
conn.scanFile(SCAN_PATH, FILE_TYPE);
}
public void onScanCompleted(String path, Uri uri)
{
try
{
if (uri != null)
{
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
}
}
finally
{
conn.disconnect();
conn = null;
}
}
}
None of the above answers are correct, including the one marked as correct.
Here's the actual correct solution:
The secret is finding the bucket/album your folder is represented as. Buckets show up after a successful MediaScan so be sure any images/videos you want to show are first scanned as demonstrated multiple times above.
Let's assume I have an indexed folder in /sdcard/myapp/myappsmediafolder:
String bucketId = "";
final String[] projection = new String[] {"DISTINCT " + MediaStore.Images.Media.BUCKET_DISPLAY_NAME + ", " + MediaStore.Images.Media.BUCKET_ID};
final Cursor cur = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
while (cur != null && cur.moveToNext()) {
final String bucketName = cur.getString((cur.getColumnIndex(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME)));
if (bucketName.equals("myappsmediafolder")) {
bucketId = cur.getString((cur.getColumnIndex(MediaStore.Images.ImageColumns.BUCKET_ID)));
break;
}
}
Now that we have the bucketId for our album we can open it with a simple intent.
Filters Video files:
Uri mediaUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
Filters Image files:
Uri mediaUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
...
if (bucketId.length() > 0) {
mediaUri = mediaUri.buildUpon()
.authority("media")
.appendQueryParameter("bucketId", bucketId)
.build();
}
Intent intent = new Intent(Intent.ACTION_VIEW, mediaUri);
startActivity(intent);
I can verify this works with the built-in Gallery app. Mileage may vary with other apps such as Google Photos.
I have yet to figure out how not to filter images/video, even though within Gallery you can select a specific Album with no filter.
I figured this out by looking at the AOSP source to the gallery app.
I don't have enough reputation to upvote or comment on his answer but ShellDude's answer allows you to put a directory URI in the gallery intent. So when the gallery app is opened it displays all of the images instead of 1.
For me, scanning my files like the answers above did not work. Querying the MediaStore.Images.Media.EXTERNAL_CONTENT_URI only worked after inserting new rows into the MediaStore.Images.Media.DATA table with the ContentResolver:
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, image.getPath());
values.put(MediaStore.Images.Media.MIME_TYPE,"image/jpeg");
contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Here is a simplified one
private MediaScannerConnection conn;
private void notifySystemWithImage(final File imageFile) {
conn = new MediaScannerConnection(this, new MediaScannerConnectionClient() {
#Override
public void onScanCompleted(String path, Uri uri) {
try {
if (uri != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "image/*");
startActivity(intent);
}
} finally {
conn.disconnect();
conn = null;
}
}
#Override
public void onMediaScannerConnected() {
conn.scanFile(imageFile.getAbsolutePath(), "*/*");
}
});
conn.connect();
}
For those who this still give activity not found exception:
You need to specify directory of your inner application folder. Not user default root if images and everything.
public class SlideShow extends Activity implements MediaScannerConnectionClient {
public String[] allFiles;
private String SCAN_PATH ;
private static final String FILE_TYPE = "*/*";
private MediaScannerConnection conn;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
File folder = new File(HistoryActivity.this.getExternalFilesDir(null)+"/a/");
allFiles = folder.list();
SCAN_PATH= HistoryActivity.this.getExternalFilesDir(null)+"/a/"+allFiles[0];
Button scanBtn = (Button) findViewById(R.id.scanBtn);
scanBtn.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
startScan();
}
});
}
private void startScan()
{
if(conn!=null)
{
conn.disconnect();
}
conn = new MediaScannerConnection(this, this);
conn.connect();
}
public void onMediaScannerConnected()
{
conn.scanFile(SCAN_PATH, FILE_TYPE);
}
public void onScanCompleted(String path, Uri uri)
{
try
{
if (uri != null)
{
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
}
}
finally
{
conn.disconnect();
conn = null;
}
}
}
works... but kitkat show only one photo. I managed to fix it for earlier versions with (updating gallery, when storing image):
public void savePhoto(Bitmap bmp)
{
File imageFileFolder = new File(context.getExternalFilesDir(null)+"/a/") ;
imageFileFolder.mkdir();
FileOutputStream out = null;
Calendar c = Calendar.getInstance();
String date = fromInt(c.get(Calendar.MONTH))
+ fromInt(c.get(Calendar.DAY_OF_MONTH))
+ fromInt(c.get(Calendar.YEAR))
+ fromInt(c.get(Calendar.HOUR_OF_DAY))
+ fromInt(c.get(Calendar.MINUTE))
+ fromInt(c.get(Calendar.SECOND));
File imageFileName = new File(imageFileFolder, date.toString() + ".jpg");
try
{
out = new FileOutputStream(imageFileName);
bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
scanPhoto(imageFileName.toString());
out = null;
} catch (Exception e)
{
e.printStackTrace();
}
}
public String fromInt(int val)
{
return String.valueOf(val);
}
public void scanPhoto(final String imageFileName)
{
msConn = new MediaScannerConnection(context,new MediaScannerConnection.MediaScannerConnectionClient()
{
public void onMediaScannerConnected()
{
msConn.scanFile(imageFileName, null);
Log.i("msClient obj in Photo Utility", "connection established");
}
public void onScanCompleted(String path, Uri uri)
{
msConn.disconnect();
Log.i("msClient obj in Photo Utility","scan completed");
}
});
msConn.connect();
}
Related
I'm referencing this link for showing images from a specific path in internal storage. But its only working with ACTION_VIEW but when I use ACTION_PICK its not showing that same path instead its simply opening gallery. Is there any way to select a single image from that specific path after showing?
public class NewActivity extends AppCompatActivity{
private static final String file_path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/fun";
private File[] allFiles ;
private String imagepath ;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File folder = new File(file_path);
allFiles = folder.listFiles();
findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new SingleMediaScanner(NewActivity.this, allFiles[0]);
}
});
}
public class SingleMediaScanner implements MediaScannerConnection.MediaScannerConnectionClient {
private MediaScannerConnection mMs;
private File mFile;
public SingleMediaScanner(Context context, File f) {
mFile = f;
mMs = new MediaScannerConnection(context, this);
mMs.connect();
}
public void onMediaScannerConnected() {
mMs.scanFile(mFile.getAbsolutePath(), null);
}
public void onScanCompleted(String path, Uri uri) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setData(uri);
startActivityForResult(intent, 100);
mMs.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==100 && resultCode==RESULT_OK){
try{
Uri selectedImageUri = data.getData();
String[] projection = {MediaStore.Images.Media.DATA};
//Cursor cursor_gallery = activity.managedQuery(selectedImageUri, projection, null, null, null);
Cursor cursor_gallery = getContentResolver().query(selectedImageUri, projection, null, null, null);
int column_index = 0;
if (cursor_gallery != null) {
column_index = cursor_gallery.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor_gallery.moveToFirst();
imagepath = cursor_gallery.getString(column_index);
cursor_gallery.close();
}
System.out.println("sammy_imagepath "+imagepath);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
When you make an ACTION_PICK intent, you're asking another application to perform an action (let them pick a file). There is no way to ensure it works a certain way- the user could just as easily have added another app that implements ACTION_PICK and does something else. So no, there is no way to ensure it will pick from that path. If you absolutely need that, you need to implement your own picker instead of using ACTION_PICK.
I have copied files from the app-private folder to either Pictures or DCIM and I want to open the gallery widget in my app and display these images.
However, my gallery widget creates a gallery of thumbnails using MediaStore id's and the newly added images dont appear there.
I tried all three solutions suggested on stackoverflow in order to refresh the media store and tell android about the existence of the new files
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, - forbidden in newer APIs
2.
MediaScannerConnection.scanFile(context,
new String[]{ pathToFile1, pathToFile2 },
null, // tried also with a String[] with the mimetype, no difference
new MediaScannerConnectionClient()
{
public void onMediaScannerConnected(){
}
public void onScanCompleted(String path, Uri uri){
// URI is null, and the gallery doesn't display the image
}
});
3.
public static void scanFile(Context context, String path, String mimeType ) {
Client client = new Client(path, mimeType);
MediaScannerConnection connection =
new MediaScannerConnection(context, client);
client.connection = connection;
connection.connect();
}
private static final class Client implements MediaScannerConnectionClient {
private final String path;
private final String mimeType;
MediaScannerConnection connection;
public Client(String path, String mimeType) {
this.path = path;
this.mimeType = mimeType;
}
#Override
public void onMediaScannerConnected() {
connection.scanFile(path, mimeType);
}
#Override
public void onScanCompleted(String path, Uri uri) {
connection.disconnect();
}
}
Again, uri is null
Why does Android make it so hard to perform such a normal, legit action?
How do I achieve this effect in Nougat?
EDIT: I also tried sending broadcast for ACTION_MEDIA_SCANNER_SCAN_FILE
And I even took into consideration this:
https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en
So now Im sending content:// instead of file:// URI but still nothing!
EDIT2:
I tried this
public static void scheduleJob(Context context) {
JobScheduler js =
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo job = new JobInfo.Builder(
MY_BACKGROUND_JOB,
new ComponentName(context, MyJobService.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.build();
js.schedule(job);
}
as explained here
https://developer.android.com/topic/performance/background-optimization.html
But again, when I open my gallery the new image is not there
Turns out I was trying to scan the path of the file I had copied to another place and then deleted, rather than the path of the newly created file.
With a combination of the media scanner and ACTION_MEDIA_SCANNER_SCAN_FILE and trying to scan the right file, I was able to refresh the media store.
I am doing the similar thing and it is working in Nougat also. Whenever I call getFilePaths(); method, It returns me fresh ArrayList of all the images present in Storage of the phone. -
public ArrayList<String> getFilePaths()
{
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.ImageColumns.DATA};
Cursor c = null;
SortedSet<String> dirList = new TreeSet<String>();
ArrayList<String> resultIAV = new ArrayList<String>();
String[] directories = null;
if (u != null)
{
c = getContentResolver().query(u, projection, null, null, null);
}
if ((c != null) && (c.moveToFirst()))
{
do
{
String tempDir = c.getString(0);
tempDir = tempDir.substring(0, tempDir.lastIndexOf("/"));
try{
dirList.add(tempDir);
}
catch(Exception e)
{
}
}
while (c.moveToNext());
directories = new String[dirList.size()];
dirList.toArray(directories);
}
for(int i=0;i<dirList.size();i++)
{
File imageDir = new File(directories[i]);
File[] imageList = imageDir.listFiles();
if(imageList == null)
continue;
for (File imagePath : imageList) {
try {
if(imagePath.isDirectory())
{
imageList = imagePath.listFiles();
}
if ( imagePath.getName().contains(".jpg")|| imagePath.getName().contains(".JPG")
|| imagePath.getName().contains(".jpeg")|| imagePath.getName().contains(".JPEG")
|| imagePath.getName().contains(".png") || imagePath.getName().contains(".PNG")
|| imagePath.getName().contains(".gif") || imagePath.getName().contains(".GIF")
|| imagePath.getName().contains(".bmp") || imagePath.getName().contains(".BMP")
)
{
String path= imagePath.getAbsolutePath();
resultIAV.add(path);
}
}
// }
catch (Exception e) {
e.printStackTrace();
}
}
}
return resultIAV;
}
Now You will get Path to all images. You can call getFilePaths().size(); to return number of images and you can compare it with previous value.
I am able to successfully record the audio and play it back. The file is being stored in the SD and has a filePath like so: /storage/emulated/0/20160516_104008. The problem is that I want the user to be able to access it via the gallery widget.
I researched this problem and this post recommended using MediaScannerConnection API, which I have implemented as follows:
MediaScannerConnection.scanFile(_reactContext,
new String[] { audioFileName }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
Here is the relevant code:
private boolean prepareAudioRecorder() {
audioRecorder = new MediaRecorder();
audioRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
audioRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
audioFileName = Environment.getExternalStorageDirectory().getAbsolutePath();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
audioFileName += "/" + timeStamp;
audioRecorder.setOutputFile(audioFileName);
audioRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
try {
audioRecorder.prepare();
return true;
} catch (IOException e) {
Log.e(TAG, "prepare() failed");
return false;
}
}
public void stopAudioRecording(final Promise promise) {
if (audioRecorderPromise != null) {
audioFile = new File(audioFileName);
releaseAudioRecorder();
storeFile();
promise.resolve("finished recording");
} else {
promise.resolve("not recording");
}
private void releaseAudioRecorder() {
if (audioRecorder != null) {
audioRecorder.stop();
audioRecorder.release();
audioRecorder = null;
if (audioRecorderPromise != null) {
// audioRecorderPromise.resolve(Uri.fromFile(audioFile).toString());
audioRecorderPromise.resolve(audioFileName);
audioRecorderPromise = null;
}
}
}
private void storeFile() {
values = new ContentValues();
values.put(MediaStore.Audio.Media.TITLE, audioFileName);
values.put(MediaStore.Audio.Media.DATE_ADDED, System.currentTimeMillis());
values.put(MediaStore.Audio.Media.MIME_TYPE, "audio/3gpp");
values.put(MediaStore.Audio.Media.DATA, audioFileName);
ContentResolver cr = _reactContext.getContentResolver();
cr.insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Uri newUri = cr.insert(base, values);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(audioFile));
_reactContext.sendBroadcast(intent);
}
You should not provide the file name but the absolute path
Refer Android Developers
Update Better use MediaScannerConnectionClient:
private MediaScannerConnectionClient mediaScannerConnectionClient = new MediaScannerConnectionClient() {
#Override
public void onMediaScannerConnected() {
mediaScannerConnection.scanFile("pathToFile/someName.extension", null);
}
#Override
public void onScanCompleted(String path, Uri uri) {
if(path.equals("pathToFile/someName.extension"))
mediaScannerConnection.disconnect();
}
};
MediaScannerConnection mediaScannerConnection = new MediaScannerConnection(context, mediaScannerConnectionClient).connect();
I'm developing an Android app that is a gallery of images in which the images are downloaded from internet for display on the screen of smathphone. Images are displayed one at a time and the application has a button to share the image that is displayed.
Following the directions I've found in some StackOverflow post which indicated that the right way to share an image was using a ContentProvider I have implemented the following code that works to share the images of certain applications (eg Twitter, Gmail ...) but does not work for others (Facebook, Yahoo, MMS ...).
Then I show the code used hoping you can help me get the correct implementation to share images in all applications.
Initially I capture the button press to share:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.menu_share) {
// I get the image being displayed on the screen
View root = getView();
ImageView imageView = (ImageView) root.findViewById(R.id.image);
Drawable imageToShareDrawable = imageView.getDrawable();
if (imageToShareDrawable instanceof BitmapDrawable) {
// I convert the image to Bitmap
Bitmap imageToShare = ((BitmapDrawable) imageToShareDrawable).getBitmap();
// Name of de image extracted from a bean property
String fileName = quote.getImage();
// I keep the image in the folder "files" of internal storage application
TempInternalStorage.createCachedFile(fileName, imageToShare, getActivity().getApplicationContext());
// I start the Activity to select the application to share the image after the intent Built with the method "getDefaultShareIntent"
startActivity(getDefaultShareIntent(fileName));
} else {
Toast.makeText(getActivity().getApplicationContext(), "Please wait, the quote is being downloaded", Toast.LENGTH_SHORT).show();
}
}
return true;
}
The method for saving the image to the internal storage of the application is as follows:
public static void createCachedFile(String fileName, Bitmap image, Context context) {
try {
File file = new File(context.getFilesDir(), fileName);
if (!file.exists()) {
FileOutputStream fos = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
}
} catch (Exception e) {
Log.e("saveTempFile()", "**** Error");
}
}
The method that constructs the Intent to share it:
private Intent getDefaultShareIntent(String fileName) {
final Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("image/jpeg");
shareIntent.putExtra(Intent.EXTRA_TEXT, "Test text");
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + CachedFileProvider.AUTHORITY + File.separator + "img" + File.separator + fileName));
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
return shareIntent;
}
Finally ContentProvider code is as follows:
public class CachedFileProvider extends ContentProvider {
private static final String CLASS_NAME = "CachedFileProvider";
public static final String AUTHORITY = "com.example.appname.cachefileprovider";
private UriMatcher uriMatcher;
#Override
public boolean onCreate() {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY, "img/*", 1);
return true;
}
#Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
String LOG_TAG = CLASS_NAME + " - openFile";
Log.i(LOG_TAG, "Called with uri: '" + uri + "'." + uri.getLastPathSegment());
switch (uriMatcher.match(uri)) {
case 1:
String fileLocation = getContext().getFilesDir() + File.separator + uri.getLastPathSegment();
ParcelFileDescriptor image = ParcelFileDescriptor.open(new File(fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);
return image;
default:
Log.i(LOG_TAG, "Unsupported uri: '" + uri + "'.");
throw new FileNotFoundException("Unsupported uri: " + uri.toString());
}
}
#Override
public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
return 0;
}
#Override
public int delete(Uri uri, String s, String[] as) {
return 0;
}
#Override
public Uri insert(Uri uri, ContentValues contentvalues) {
return null;
}
#Override
public String getType(Uri uri) {
return null;
}
#Override
public Cursor query(Uri uri, String[] projection, String s, String[] as1, String s1) {
MatrixCursor c = null;
Log.i(">>>> projection", java.util.Arrays.toString(projection));
String fileLocation = getContext().getFilesDir() + File.separator + uri.getLastPathSegment();
File file = new File(fileLocation);
long time = System.currentTimeMillis();
c = new MatrixCursor(new String[] { "_id", "_data", "orientation", "mime_type", "datetaken", "_display_name" });
c.addRow(new Object[] { 0, file, 0, "image/jpeg", time, uri.getLastPathSegment() });
return c;
}
#Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
return null;
}
}
I have found that when the image is sharing some applications only call the method "query" (these are where the code does not work and I can not share the image) while there are others that also call the method "query" also call the method "openFile" and these do work and I can share the image.
I hope you can help me, thank you very much in advance.
As #Sun Ning-s comment noted some "share target apps" can handle URI-s starting with "content://.." which you have implemented.
Other apps handle file uri-s starting with "file://...." so you have to implement a 2nd share menue "share as file"
private Intent getFileShareIntent(String fullPathTofile) {
final Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("image/jpeg");
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fullPathTofile));
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
return shareIntent;
}
You can use the android app intentintercept to find out what other "share source apps" provide.
I'm using these 2 classes to request and retrieve the picture from the Gallery. This code works well in Gingerbread and below but in Honeycomb on my Xoom it fails.
The behavior I see it it writes a blank file but the gallery doesn't write the chosen picture to that file. In addition, the file is not visible in Windows I have to go to the DDMS tab to see the file be created. It has rw access for owner and group but not everybody.
Adapted From: Retrieve Picasa Image for Upload from Gallery
public static class GetImage implements IIntentBuilderForResult {
public String TypeFilter = "image/*";
public boolean ForceDefaultHandlers = false;
public Bitmap.CompressFormat CompressFormat = Bitmap.CompressFormat.PNG;
private Intent intent = null;
private String TemporaryImagePath = null;
public void prepareIntent(Context context) {
try {
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
dir.mkdirs();
File tempFile = new File(dir, "galleryresult-temp.png");
//.createTempFile("GalleryResult", ".png");
TemporaryImagePath = tempFile.getAbsolutePath();
tempFile.getParentFile().mkdirs();
tempFile.createNewFile();
Logger.d("IsFile= " + tempFile.isFile());
tempFile.setWritable(true, false);
tempFile.setReadable(true, false);
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(TypeFilter);
if (ForceDefaultHandlers) {
intent.addCategory(Intent.CATEGORY_DEFAULT);
}
final Uri uri = Uri.fromFile(tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
final String formatName = CompressFormat.name();
intent.putExtra("outputFormat", formatName);
} catch (Exception e) {
}
}
public Intent getIntent() {
return intent;
}
public Bundle getResultBundle() {
Bundle data = new Bundle();
data.putString("transientImagePath", TemporaryImagePath);
return data;
}
}
public abstract static class GetImageResult extends ActivityResultHandlerHelper {
public Bitmap bitmapResult = null;
public void onPrepareResult() {
bitmapResult = null;
Uri imageUri = null;
String filePath = null;
boolean fromTransientPath = false;
String tempFilePath = null;
if(resultBundle != null) {
tempFilePath = resultBundle.getString("transientImagePath");
File tempFile = new File(tempFilePath);
imageUri = Uri.fromFile(tempFile);
}
if(imageUri == null || imageUri.toString().length() == 0) {
imageUri = data.getData();
} else {
fromTransientPath = true;
}
if(imageUri != null) {
if(imageUri.getScheme().equals("file")) {
filePath = imageUri.getPath();
} else if(imageUri.getScheme().equals("content")) {
filePath = findPictureFilePath(context, imageUri);
}
if(filePath != null) {
bitmapResult = BitmapFactory.decodeFile(filePath);
if(fromTransientPath) {
//File delTarget = new File(filePath);
//delTarget.delete();
}
}
}
}
}
public static final String findPictureFilePath(Context context, Uri dataUri) {
String filePath = null;
final String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(dataUri, projection,
null, null, null);
int data_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
if (cursor.moveToFirst()) {
filePath = cursor.getString(data_index);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return filePath;
}
Launch intent to get the photo.
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
activity.startActivityForResult(intent, requestCode);
Accept the photo on return.
final InputStream is = context.getContentResolver().openInputStream(intent.getData());
final Bitmap imageData = BitmapFactory.decodeStream(is, null, options);
is.close();
This issue was so maddening that I wrote a whole article about how to do it properly. Or at least the best possible way.
http://androidfragments.blogspot.com/2012/02/loading-bitmaps-from-gallery.html