• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.test.mediahelper;
18 
19 import android.content.ContentResolver;
20 import android.content.ContentUris;
21 import android.content.Context;
22 import android.database.Cursor;
23 import android.net.Uri;
24 import android.provider.MediaStore;
25 
26 import com.google.common.collect.ImmutableList;
27 
28 import java.io.FileDescriptor;
29 import java.io.FileNotFoundException;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.List;
33 
34 /** Helper functions for interacting with android {@link MediaStore}. */
35 public class MediaStoreHelper {
36     private static MediaStoreHelper sInstance;
37     private ContentResolver mContentResolver;
38 
MediaStoreHelper(Context context)39     private MediaStoreHelper(Context context) {
40         mContentResolver = context.getContentResolver();
41     }
42 
getInstance(Context context)43     public static MediaStoreHelper getInstance(Context context) {
44         if (sInstance == null) {
45             sInstance = new MediaStoreHelper(context);
46         }
47         return sInstance;
48     }
49 
50     /**
51      * Returns the maximum value of {@link MediaStore.MediaColumns.GENERATION_ADDED} at given URI.
52      *
53      * @param uri The URI, the content:// style uri, for the content to retrieve from {@link
54      *     MediaStore}. For example, to retrieve from image media table, use
55      *     "content://media/external/images/media".
56      * @param selection A filter declaring which rows to return, formatted as an SQL WHERE clause
57      *     (excluding the WHERE itself). Passing null will return all rows for the given URI.
58      * @param selectionArgs You may include ?s in selection, which will be replaced by the values
59      *     from selectionArgs, in the order that they appear in the selection. The values will be
60      *     bound as Strings.
61      * @return A long value of the maximum generation. Returns -1L if no records find.
62      */
getMaxGeneration(Uri uri, String selection, String[] selectionArgs)63     public long getMaxGeneration(Uri uri, String selection, String[] selectionArgs) {
64         long maxGen = -1L;
65         Cursor cursor =
66                 mContentResolver.query(
67                         uri,
68                         new String[] {MediaStore.MediaColumns.GENERATION_ADDED},
69                         selection,
70                         selectionArgs,
71                         MediaStore.MediaColumns.GENERATION_ADDED + " DESC");
72         if (cursor != null) {
73             if (cursor.moveToFirst()) {
74                 maxGen =
75                         cursor.getLong(
76                                 cursor.getColumnIndex(MediaStore.MediaColumns.GENERATION_ADDED));
77             }
78             cursor.close();
79         }
80         return maxGen;
81     }
82 
83     /**
84      * Returns a value list of {@link MediaStore.MediaColumns#_ID}.
85      *
86      * @param uri The URI, the content:// style uri, for the content to retrieve from {@link
87      *     MediaStore}. For example, to retrieve from image media table, use
88      *     "content://media/external/images/media".
89      * @param selection A filter declaring which rows to return, formatted as an SQL WHERE clause
90      *     (excluding the WHERE itself). Passing null will return all rows for the given URI.
91      * @param selectionArgs You may include ?s in selection, which will be replaced by the values
92      *     from selectionArgs, in the order that they appear in the selection. The values will be
93      *     bound as Strings.
94      * @param fromGen Generation added. The id of the records returned all have generation bigger
95      *     than this value. It is also formatted as a WHERE clause together with what specified in
96      *     selection.
97      * @return A list of record ids.
98      */
getListOfIdsFromMediaStore( Uri uri, String selection, String[] selectionArgs, long fromGen)99     public List<Long> getListOfIdsFromMediaStore(
100             Uri uri, String selection, String[] selectionArgs, long fromGen) {
101         ImmutableList.Builder builder = new ImmutableList.Builder();
102         String selectionStr =
103                 MediaStore.MediaColumns.GENERATION_ADDED + ">" + String.valueOf(fromGen);
104         if (selection != null && !selection.isEmpty()) {
105             selectionStr = selectionStr + " AND " + selection;
106         }
107         Cursor cursor =
108                 mContentResolver.query(
109                         uri,
110                         new String[] {
111                             MediaStore.MediaColumns._ID, MediaStore.MediaColumns.GENERATION_ADDED
112                         },
113                         selectionStr,
114                         selectionArgs,
115                         null);
116         try {
117             while (cursor != null && cursor.moveToNext()) {
118                 builder.add(cursor.getLong(cursor.getColumnIndex(MediaStore.MediaColumns._ID)));
119             }
120         } finally {
121             if (cursor != null) {
122                 cursor.close();
123             }
124         }
125         return builder.build();
126     }
127 
128     /**
129      * Returns a list of media {@link FileDescriptor} for specific MIME type.
130      *
131      * @param uri The URI, the content:// style uri, for the content to retrieve from {@link
132      *     MediaStore}. For example, to retrieve from image media table, use
133      *     "content://media/external/images/media".
134      * @param mimeType The MIME type of the media item, eg. "image/jpeg". {@see
135      *     MediaStore.MediaColumns#MIME_TYPE}
136      * @param fromGen Generation added. The returned records all have generation bigger than this.
137      * @param selection A filter declaring which rows to return, formatted as an SQL WHERE clause
138      *     (excluding the WHERE itself). Passing null will return all rows for the given URI.
139      * @param selectionArgs You may include ?s in selection, which will be replaced by the values
140      *     from selectionArgs, in the order that they appear in the selection. The values will be
141      *     bound as Strings.
142      * @return A list of media {@link FileDescriptor} for specified type.
143      */
getMediaFileDescriptors( Uri uri, String mimeType, String selection, String[] selectionArgs, long fromGen)144     public List<FileDescriptor> getMediaFileDescriptors(
145             Uri uri, String mimeType, String selection, String[] selectionArgs, long fromGen) {
146         ImmutableList.Builder fileListBuilder = new ImmutableList.Builder();
147         StringBuilder selectionBuilder = new StringBuilder();
148         List<String> argList = new ArrayList<>();
149         selectionBuilder.append(MediaStore.MediaColumns.IS_PENDING + "=?");
150         argList.add("0");
151         if (mimeType != null) {
152             selectionBuilder.append(" AND ");
153             selectionBuilder.append(MediaStore.MediaColumns.MIME_TYPE + "=?");
154             argList.add(mimeType);
155         }
156         if (selection != null && !selection.isEmpty()) {
157             selectionBuilder.append(" AND ");
158             selectionBuilder.append(selection);
159         }
160         if (selectionArgs != null) {
161             argList.addAll(Arrays.asList(selectionArgs));
162         }
163         List<Long> ids =
164                 getListOfIdsFromMediaStore(
165                         uri,
166                         selectionBuilder.toString(),
167                         argList.toArray(new String[argList.size()]),
168                         fromGen);
169         for (long id : ids) {
170             Uri fileUri = ContentUris.withAppendedId(uri, id);
171             try {
172                 FileDescriptor fileDescriptor =
173                         mContentResolver.openFileDescriptor(fileUri, "r").getFileDescriptor();
174                 fileListBuilder.add(fileDescriptor);
175             } catch (FileNotFoundException e) {
176                 throw new RuntimeException("Unable to open file descriptor at " + uri, e);
177             }
178         }
179         return fileListBuilder.build();
180     }
181 }
182