Home » Android » android – Gallery with folder filter

android – Gallery with folder filter

Posted by: admin June 15, 2020 Leave a comment

Questions:

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.

How to&Answers:

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

Answer:

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.

Answer:

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

Answer:

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

Answer:

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