Question

I need to scan the Android media store for image folder paths which I pass to another activity which displays images from the selected folder. My current code which does the job, but crashes on certain image paths and extensions (e.g. some image &%^$%*5.png, and some image.bin):

final String[] columns = {
    MediaStore.Images.Media.DATA,
    MediaStore.Images.Media._ID,
    MediaStore.Images.Media.DISPLAY_NAME,
    MediaStore.Images.Media.BUCKET_DISPLAY_NAME
};
final String orderBy = MediaStore.Images.Media.DISPLAY_NAME;

Cursor cursor = activity.getContentResolver().query(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
        null, orderBy);

mExternalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();

mCount = cursor.getCount();
// mAbsolutePath is the absolute path (e.g. //emulated/0/folder/picture.png)
mAbsolutePath = new String[mCount];
mDisplayName = new String[mCount];
// mFolderIntentPath is what will eventually become the folder path (e.g. //emulated/0/folder/)
mFolderIntentPath = new String[mCount];
mBucket = new String[mCount];

for (int i = 0; i < this.mCount; i++) {
    cursor.moveToPosition(i);
    int absolutePathColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
    int displayNameColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME);
    int bucketColumnIndex = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);

    mAbsolutePath[i]= cursor.getString(absolutePathColumnIndex);
    mDisplayName[i] = cursor.getString(displayNameColumnIndex);
    mBucket[i] = cursor.getString(bucketColumnIndex);
    mFolderIntentPath[i] = mAbsolutePath[i].substring(0, mAbsolutePath[i].length() - mDisplayName[i].length());
}

Is there a better way of getting the image folder paths?

EDIT: Here is the logcat:

05-05 04:11:36.200  13580-13580/com.sinisa.eyesonly E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.StringIndexOutOfBoundsException: length=64; regionStart=20; regionLength=-1
            at java.lang.String.startEndAndLength(String.java:583)
            at java.lang.String.substring(String.java:1464)
            at com.sinisa.eyesonly.gui.fragment.FragmentGallery.scanMediaStoreFolders(FragmentGallery.java:113)
            at com.sinisa.eyesonly.gui.fragment.FragmentGallery.onCreateView(FragmentGallery.java:75)
            at android.app.Fragment.performCreateView(Fragment.java:1695)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:885)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)
            at android.app.BackStackRecord.run(BackStackRecord.java:682)
            at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
            at android.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:474)
            at android.support.v13.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:145)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:1068)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
            at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1436)
            at android.view.View.measure(View.java:15513)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4827)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:15513)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4827)
            at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
            at android.view.View.measure(View.java:15513)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4827)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2176)
            at android.view.View.measure(View.java:15513)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1874)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1089)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1265)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
            at android.view.Choreographer.doCallbacks(Choreographer.java:562)
            at android.view.Choreographer.doFrame(Choreographer.java:532)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
            at android.os.Handler.handleCallback(Handler.java:725)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5039)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
            at dalvik.system.NativeStart.main(Native Method)
05-05 04:11:36.216      387-669/? W/ActivityManager﹕ Force finishing activity com.sinisa.eyesonly/.gui.MainActivity

When i id call Log.d on mDistinct and mAbsolutePath like this:

            mAbsolutePath[i]= cursor.getString(absolutePathColumnIndex);
            Log.d("bitmap","abs" + mAbsolutePath[i]);
            mDisplayName[i] = cursor.getString(displayNameColumnIndex);
            Log.d("bitmap","dis" + mDisplayName[i]);

i get:

05-05 04:11:36.184  13580-13580/com.sinisa.eyesonly D/bitmap﹕ abs/storage/emulated/0/Snapchat/Snapchat-20140425090242.jpg
05-05 04:11:36.184  13580-13580/com.sinisa.eyesonly D/bitmap﹕ disSnapchat-20140425090242.jpg
05-05 04:11:36.184  13580-13580/com.sinisa.eyesonly D/bitmap﹕ abs/storage/emulated/0/Universal Image Loader @#&=+-_.,!()~'%20.png
05-05 04:11:36.184  13580-13580/com.sinisa.eyesonly D/bitmap﹕ disUniversal Image Loader @#&=+-_.,!()~'%20.png
Was it helpful?

Solution

Your problem is on this line:

mFolderIntentPath[i] = mAbsolutePath[i].substring(0, mAbsolutePath[i].length() - mDisplayName[i].length());

According to the exception you're getting, mDisplayName[i].length() > mAbsolutePath[i].length(). I'm guessing that this is because the display name is not always the name of the file. If you want to strip off the base name to get just the directory name, you might want to try to get the index at which to cut it off in a different way, say like

mFolderIntentPath[i] = mAbsolutePath[i].substring(0, mAbsolutePath[i].lastIndexOf('/'));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top