javaandroidandroid-galleryandroid-cursor

How can I get photos from MediaStore in 2 different time periods in Android Studio?


The app analyzes emotion by taking all the photos in the phone's MediaStore and sending the photos containing the face(s) in the loop to our model. However, instead of looking at the whole MediaStore again at each launch, we only need to look at the newly added photos.

However, when we first install the app, all photos are successfully retrieved, but when we exit the app, download a new photo and re-enter the app, we have the problem that only the newly added photos are not retrieved.

public static void listOfImages(Context context) {
    Uri uri;
    String ablosutePathOfImage;
    emotionDatabase = 
    EmotionDatabase.getEmotionDatabase(context);

    Long currentTime = System.currentTimeMillis();
    String timeStamp = currentTime.toString();
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    String lastPhotoDate = sharedPreferences.getString("last_photo_date",null);;

    uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    String [] projection = {MediaStore.MediaColumns.DATA,MediaStore.Images.Media.DATE_TAKEN};
    String orderBy = MediaStore.Images.Media.DATE_TAKEN + " DESC";

    if(lastPhotoDate == null){
       cursor = context.getContentResolver().query(uri,projection,null,null,orderBy);
    }
   else{
       cursor = context.getContentResolver().query(uri, projection,
       MediaStore.Images.Media.DATE_TAKEN + ">? and " + 
       MediaStore.Images.Media.DATE_TAKEN + "<?",
       new String[] {lastPhotoDate , timeStamp},
       orderBy);
}
    int column_index_data = 
cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);

    //face detection standard classify yapan kısım
    if(cursor.moveToFirst()){
        ablosutePathOfImage = cursor.getString(column_index_data);
        File file = new File(ablosutePathOfImage);
        Long photoDate = file.lastModified();
        lastPhotoDate = photoDate.toString();
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("last_photo_date", lastPhotoDate);
        editor.apply();

        do {
            ablosutePathOfImage = cursor.getString(column_index_data);
            final Bitmap myBitmap = BitmapFactory.decodeFile(ablosutePathOfImage);
            FaceDetector faceDetector =new FaceDetector.Builder(context.getApplicationContext())
                    .setTrackingEnabled(false)
                    .setLandmarkType(FaceDetector.ALL_LANDMARKS)
                    .setMode(FaceDetector.FAST_MODE)
                    .build();
            Frame frame = new Frame.Builder().setBitmap(myBitmap).build();
            SparseArray<Face> sparseArray = faceDetector.detect(frame);

            for (int i = 0; i < sparseArray.size(); i++) {
                Face face = sparseArray.valueAt(i);
                float x1 = face.getPosition().x;
                float y1 = face.getPosition().y;

                Bitmap faceBitmap = Bitmap.createBitmap(
                        myBitmap,
                        (int) x1,
                        (int) y1,
                        (int) face.getWidth(),
                        (int) face.getHeight());
                classifyEmotions(faceBitmap, context, ablosutePathOfImage);
            }
        } while (cursor.moveToNext());
    }
}

We keep the last photo date of the last photo in the gallery in seconds in the lastPhotoDate variable and store this data with SharedPreferences.

If the last_photo_date we store in SharedPreferences is empty, the lastPhotoDate variable is assigned the value "null", if it is not empty, the value of last_photo_date is assigned.

When the application runs, if there are any new photo(s) in the time period from the value in the lastPhotoDate variable to the value of the timeStamp variable that holds the system time, they are assigned to the cursor.

I checked the value of the lastPhotoDate variable and it returned the value of the last photo scanned by the app. The timeStamp variable returned the value of the phone's current time when the listOfImages function was running.

When I add a new photo and open the application, it never enters the "if (cursor.moveToFirst()) {}" statement.

There might be a bug in my cursor query:

cursor = context.getContentResolver().query(uri, projection,
   MediaStore.Images.Media.DATE_TAKEN + ">? and " + 
   MediaStore.Images.Media.DATE_TAKEN + "<?",
   new String[] {lastPhotoDate , timeStamp},
   orderBy);

OR

My code block where I get the date of the last photo may be wrong:

ablosutePathOfImage = cursor.getString(column_index_data);
File file = new File(ablosutePathOfImage);
Long photoDate = file.lastModified();
lastPhotoDate = photoDate.toString();
SharedPreferences.Editor editor editor = sharedPreferences.edit();
editor.putString("last_photo_date", lastPhotoDate);
editor.apply();

Solution

  • public static void listOfImages(Context context) {
    
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        long lastPhotoDate = sharedPreferences.getLong("last_photo_date", -1);
    
        String[] projection = { MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_ADDED };
        String selection = null;
        String[] selectionArgs = null;
        String sortOrder = MediaStore.Images.Media.DATE_ADDED + " DESC";
    
        if (lastPhotoDate != -1){
            selection = MediaStore.Images.Media.DATE_ADDED + ">?";
            selectionArgs = new String[] { String.valueOf(lastPhotoDate) };
        }
    
        Cursor cursor = context.getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                projection,
                selection,
                selectionArgs,
                sortOrder
        );
    
        if (cursor != null && cursor.moveToFirst()) {
            do {
                String imagePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
                long dateTaken = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putLong("last_photo_date", dateTaken);
                editor.apply();
    
                final Bitmap myBitmap = BitmapFactory.decodeFile(imagePath);
                FaceDetector faceDetector = new FaceDetector.Builder(context.getApplicationContext())
                        .setTrackingEnabled(false)
                        .setLandmarkType(FaceDetector.ALL_LANDMARKS)
                        .setMode(FaceDetector.FAST_MODE)
                        .build();
                Frame frame = new Frame.Builder().setBitmap(myBitmap).build();
                SparseArray<Face> sparseArray = faceDetector.detect(frame);
    
                for (int i = 0; i < sparseArray.size(); i++) {
                    Face face = sparseArray.valueAt(i);
                    Bitmap faceBitmap = Bitmap.createBitmap(
                            myBitmap,
                            (int) face.getPosition().x,
                            (int) Math.abs(face.getPosition().y),
                            (int) face.getWidth(),
                            (int) face.getHeight());
                    classifyEmotions(faceBitmap, context, imagePath);
                }
            } while (cursor.moveToNext());
            cursor.close();
        }
    }
    

    We were experiencing an issue because we couldn't access the MediaStore.Images.Media.DATE_TAKEN property of MesiaStore. I edited the code and resolved the issue by using the DATE_ADDED property of MesiaStore instead.