blob: 67bb6ac891d348b5ac676b26a208e150f158e9fb [file] [log] [blame]
Jon Miranda16ea1b12017-12-12 14:52:48 -08001/*
2 * Copyright (C) 2017 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 */
16package com.android.wallpaper.picker.individual;
17
18import android.Manifest.permission;
19import android.app.Activity;
20import android.content.Context;
21import android.content.pm.PackageManager;
22import android.database.Cursor;
23import android.net.Uri;
24import android.os.AsyncTask;
25import android.provider.MediaStore;
Jon Miranda16ea1b12017-12-12 14:52:48 -080026import android.view.View;
27import android.widget.ImageView;
28
29import com.android.wallpaper.R;
30import com.android.wallpaper.asset.Asset;
31import com.android.wallpaper.asset.ContentUriAsset;
32import com.android.wallpaper.picker.MyPhotosLauncher;
33
Sunny Goyal8600a3f2018-08-15 12:48:01 -070034import androidx.annotation.Nullable;
35import androidx.recyclerview.widget.RecyclerView.ViewHolder;
36
Jon Miranda16ea1b12017-12-12 14:52:48 -080037/**
38 * ViewHolder for a "my photos" tile presented in an individual category grid.
39 */
40public class MyPhotosViewHolder extends ViewHolder implements View.OnClickListener,
41 MyPhotosLauncher.PermissionChangedListener {
42
43 private Activity mActivity;
44 private ImageView mThumbnailView;
45 private ImageView mOverlayIconView;
46
47 /* package */ MyPhotosViewHolder(Activity activity, int tileHeightPx, View itemView) {
48 super(itemView);
49
50 mActivity = activity;
51 itemView.getLayoutParams().height = tileHeightPx;
52
53 itemView.findViewById(R.id.tile).setOnClickListener(this);
54
55 mThumbnailView = (ImageView) itemView.findViewById(R.id.thumbnail);
56 mOverlayIconView = (ImageView) itemView.findViewById(R.id.overlay_icon);
57 }
58
59 /**
60 * Fetches a thumbnail asset to represent "my photos" (as the most recently taken photo from the
61 * user's custom photo collection(s)) and calls back to the main thread with the asset.
62 */
63 private static void fetchThumbnail(final Context context, final AssetListener listener) {
64 if (!isReadExternalStoragePermissionGranted(context)) {
65 // MediaStore.Images.Media.EXTERNAL_CONTENT_URI requires the READ_EXTERNAL_STORAGE permission.
66 listener.onAssetRetrieved(null);
67 }
68
69 new AsyncTask<Void, Void, Asset>() {
70 @Override
71 protected Asset doInBackground(Void... params) {
72 String[] projection = new String[]{
73 MediaStore.Images.ImageColumns._ID,
74 MediaStore.Images.ImageColumns.DATE_TAKEN,
75 };
76 String sortOrder = MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC LIMIT 1";
77 Cursor cursor = context.getContentResolver().query(
78 MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
79 projection,
80 null /* selection */,
81 null /* selectionArgs */,
82 sortOrder);
83
84 Asset asset = null;
85 if (cursor != null) {
86 if (cursor.moveToNext()) {
87 asset = new ContentUriAsset(context, Uri.parse(
88 MediaStore.Images.Media.EXTERNAL_CONTENT_URI + "/" + cursor.getString(0)));
89 }
90 cursor.close();
91 }
92
93 return asset;
94 }
95
96 @Override
97 protected void onPostExecute(Asset thumbnail) {
98 listener.onAssetRetrieved(thumbnail);
99 }
100 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
101 }
102
103 /**
104 * Returns whether READ_EXTERNAL_STORAGE has been granted for the application.
105 */
106 private static boolean isReadExternalStoragePermissionGranted(Context context) {
107 return context.getPackageManager().checkPermission(permission.READ_EXTERNAL_STORAGE,
108 context.getPackageName()) == PackageManager.PERMISSION_GRANTED;
109 }
110
111 @Override
112 public void onClick(View view) {
113 ((MyPhotosLauncher) mActivity).requestCustomPhotoPicker(this);
114 }
115
116 /**
117 * Draws the overlay icon or last-taken photo as thumbnail for the ViewHolder depending on whether
118 * storage permission has been granted to the app.
119 */
120 /* package */ void bind() {
121 if (isReadExternalStoragePermissionGranted(mActivity)) {
122 mOverlayIconView.setVisibility(View.GONE);
123 drawThumbnail();
124 } else {
125 mOverlayIconView.setVisibility(View.VISIBLE);
126 mOverlayIconView.setImageDrawable(mActivity.getDrawable(
127 R.drawable.myphotos_empty_tile_illustration));
128 }
129 }
130
131 @Override
132 public void onPermissionsGranted() {
133 bind();
134 }
135
136 @Override
137 public void onPermissionsDenied(boolean dontAskAgain) {
138 // No-op
139 }
140
141 private void drawThumbnail() {
142 fetchThumbnail(mActivity, new AssetListener() {
143 @Override
144 public void onAssetRetrieved(@Nullable Asset thumbnail) {
145 if (thumbnail == null) {
146 return;
147 }
148
149 thumbnail.loadDrawable(mActivity, mThumbnailView,
150 mActivity.getResources().getColor(R.color.secondary_color));
151 }
152 });
153 }
154
155 private interface AssetListener {
156 /**
157 * Called when the requested Asset is retrieved.
158 */
159 void onAssetRetrieved(@Nullable Asset asset);
160 }
161}