1 /* 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 */ 16 package com.android.wallpaper.picker.individual; 17 18 import static com.android.wallpaper.picker.WallpaperPickerDelegate.PREVIEW_LIVE_WALLPAPER_REQUEST_CODE; 19 import static com.android.wallpaper.picker.WallpaperPickerDelegate.PREVIEW_WALLPAPER_REQUEST_CODE; 20 21 import android.app.Activity; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.res.Resources.NotFoundException; 25 import android.os.Bundle; 26 import android.util.Log; 27 import android.view.MenuItem; 28 import android.widget.Toast; 29 30 import androidx.appcompat.widget.Toolbar; 31 import androidx.fragment.app.Fragment; 32 import androidx.fragment.app.FragmentManager; 33 34 import com.android.wallpaper.R; 35 import com.android.wallpaper.model.Category; 36 import com.android.wallpaper.model.CategoryProvider; 37 import com.android.wallpaper.model.CategoryReceiver; 38 import com.android.wallpaper.model.InlinePreviewIntentFactory; 39 import com.android.wallpaper.model.LiveWallpaperInfo; 40 import com.android.wallpaper.model.PickerIntentFactory; 41 import com.android.wallpaper.model.WallpaperCategory; 42 import com.android.wallpaper.model.WallpaperInfo; 43 import com.android.wallpaper.module.Injector; 44 import com.android.wallpaper.module.InjectorProvider; 45 import com.android.wallpaper.module.WallpaperPersister; 46 import com.android.wallpaper.picker.BaseActivity; 47 import com.android.wallpaper.picker.PreviewActivity.PreviewActivityIntentFactory; 48 import com.android.wallpaper.util.DiskBasedLogger; 49 import com.android.wallpaper.util.ResourceUtils; 50 import com.android.wallpaper.widget.BottomActionBar; 51 import com.android.wallpaper.widget.BottomActionBar.BottomActionBarHost; 52 53 /** 54 * Activity that can be launched from the Android wallpaper picker and allows users to pick from 55 * various wallpapers and enter a preview mode for specific ones. 56 */ 57 public class IndividualPickerActivity extends BaseActivity implements BottomActionBarHost, 58 IndividualPickerFragment.IndividualPickerFragmentHost { 59 private static final String TAG = "IndividualPickerAct"; 60 private static final String EXTRA_CATEGORY_COLLECTION_ID = 61 "com.android.wallpaper.category_collection_id"; 62 private static final String EXTRA_WALLPAPER_ID = "com.android.wallpaper.wallpaper_id"; 63 private static final String KEY_CATEGORY_COLLECTION_ID = "key_category_collection_id"; 64 65 private InlinePreviewIntentFactory mPreviewIntentFactory; 66 private WallpaperPersister mWallpaperPersister; 67 private Category mCategory; 68 private String mCategoryCollectionId; 69 private String mWallpaperId; 70 71 @Override onCreate(Bundle savedInstanceState)72 protected void onCreate(Bundle savedInstanceState) { 73 super.onCreate(savedInstanceState); 74 75 mPreviewIntentFactory = new PreviewActivityIntentFactory(); 76 Injector injector = InjectorProvider.getInjector(); 77 mWallpaperPersister = injector.getWallpaperPersister(this); 78 79 mCategoryCollectionId = (savedInstanceState == null) 80 ? getIntent().getStringExtra(EXTRA_CATEGORY_COLLECTION_ID) 81 : savedInstanceState.getString(KEY_CATEGORY_COLLECTION_ID); 82 mWallpaperId = getIntent().getStringExtra(EXTRA_WALLPAPER_ID); 83 84 if (mWallpaperId == null) { // Normal case 85 initializeUI(); 86 } else { // Deeplink to preview page case 87 setContentView(R.layout.activity_loading); 88 } 89 90 CategoryProvider categoryProvider = injector.getCategoryProvider(this); 91 categoryProvider.fetchCategories(new CategoryReceiver() { 92 @Override 93 public void onCategoryReceived(Category category) { 94 // Do nothing. 95 } 96 97 @Override 98 public void doneFetchingCategories() { 99 mCategory = categoryProvider.getCategory(mCategoryCollectionId); 100 if (mCategory == null) { 101 DiskBasedLogger.e(TAG, "Failed to find the category: " 102 + mCategoryCollectionId, IndividualPickerActivity.this); 103 // We either were called with an invalid collection Id, or we're restarting 104 // with no saved state, or with a collection id that doesn't exist anymore. 105 // In those cases, we cannot continue, so let's just go back. 106 finish(); 107 return; 108 } 109 110 // Show the preview of the specific wallpaper directly. 111 if (mWallpaperId != null) { 112 ((WallpaperCategory) mCategory).fetchWallpapers(getApplicationContext(), 113 wallpapers -> { 114 for (WallpaperInfo wallpaper : wallpapers) { 115 if (wallpaper.getWallpaperId().equals(mWallpaperId)) { 116 showPreview(wallpaper); 117 return; 118 } 119 } 120 // No matched wallpaper, finish the activity. 121 finish(); 122 }, false); 123 } else { 124 onCategoryLoaded(); 125 } 126 } 127 }, false); 128 } 129 onCategoryLoaded()130 private void onCategoryLoaded() { 131 setTitle(mCategory.getTitle()); 132 getSupportActionBar().setTitle(mCategory.getTitle()); 133 } 134 initializeUI()135 private void initializeUI() { 136 setContentView(R.layout.activity_individual_picker); 137 138 // Set toolbar as the action bar. 139 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 140 setSupportActionBar(toolbar); 141 142 FragmentManager fm = getSupportFragmentManager(); 143 Fragment fragment = fm.findFragmentById(R.id.fragment_container); 144 145 getSupportActionBar().setDisplayHomeAsUpEnabled(true); 146 147 toolbar.getNavigationIcon().setTint( 148 ResourceUtils.getColorAttr(this, android.R.attr.textColorPrimary) 149 ); 150 toolbar.getNavigationIcon().setAutoMirrored(true); 151 152 if (fragment == null) { 153 fragment = InjectorProvider.getInjector() 154 .getIndividualPickerFragment(mCategoryCollectionId); 155 fm.beginTransaction().add(R.id.fragment_container, fragment).commit(); 156 } 157 } 158 159 @Override onOptionsItemSelected(MenuItem item)160 public boolean onOptionsItemSelected(MenuItem item) { 161 int id = item.getItemId(); 162 if (id == android.R.id.home) { 163 // Handle Up as a Global back since the only entry point to IndividualPickerActivity is 164 // from TopLevelPickerActivity. 165 onBackPressed(); 166 return true; 167 } 168 return false; 169 } 170 171 @Override onActivityResult(int requestCode, int resultCode, Intent data)172 public void onActivityResult(int requestCode, int resultCode, Intent data) { 173 super.onActivityResult(requestCode, resultCode, data); 174 175 boolean shouldShowMessage = false; 176 switch (requestCode) { 177 case PREVIEW_LIVE_WALLPAPER_REQUEST_CODE: 178 shouldShowMessage = true; 179 case PREVIEW_WALLPAPER_REQUEST_CODE: 180 if (resultCode == Activity.RESULT_OK) { 181 mWallpaperPersister.onLiveWallpaperSet(); 182 183 // The wallpaper was set, so finish this activity with result OK. 184 finishWithResultOk(shouldShowMessage); 185 } 186 break; 187 default: 188 Log.e(TAG, "Invalid request code: " + requestCode); 189 } 190 191 // In deeplink to preview page case, this activity is just a middle layer 192 // which redirects to preview activity. We should make sure this activity is finished 193 // after getting the result in this case. Otherwise it will show an empty activity. 194 if (mWallpaperId != null && !isFinishing()) { 195 setResult(resultCode); 196 finish(); 197 } 198 } 199 200 /** 201 * Shows the preview activity for the given wallpaper. 202 */ showPreview(WallpaperInfo wallpaperInfo)203 public void showPreview(WallpaperInfo wallpaperInfo) { 204 mWallpaperPersister.setWallpaperInfoInPreview(wallpaperInfo); 205 wallpaperInfo.showPreview(this, mPreviewIntentFactory, 206 wallpaperInfo instanceof LiveWallpaperInfo ? PREVIEW_LIVE_WALLPAPER_REQUEST_CODE 207 : PREVIEW_WALLPAPER_REQUEST_CODE); 208 } 209 finishWithResultOk(boolean shouldShowMessage)210 private void finishWithResultOk(boolean shouldShowMessage) { 211 if (shouldShowMessage) { 212 try { 213 Toast.makeText(this, R.string.wallpaper_set_successfully_message, 214 Toast.LENGTH_SHORT).show(); 215 } catch (NotFoundException e) { 216 Log.e(TAG, "Could not show toast " + e); 217 } 218 } 219 overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 220 setResult(Activity.RESULT_OK); 221 finish(); 222 } 223 224 @Override onSaveInstanceState(Bundle bundle)225 protected void onSaveInstanceState(Bundle bundle) { 226 super.onSaveInstanceState(bundle); 227 228 bundle.putString(KEY_CATEGORY_COLLECTION_ID, mCategoryCollectionId); 229 } 230 231 @Override getBottomActionBar()232 public BottomActionBar getBottomActionBar() { 233 return findViewById(R.id.bottom_actionbar); 234 } 235 236 @Override isHostToolbarShown()237 public boolean isHostToolbarShown() { 238 return true; 239 } 240 241 @Override setToolbarTitle(CharSequence title)242 public void setToolbarTitle(CharSequence title) { 243 setTitle(title); 244 getSupportActionBar().setTitle(title); 245 } 246 247 @Override setToolbarMenu(int menuResId)248 public void setToolbarMenu(int menuResId) { 249 250 } 251 252 @Override removeToolbarMenu()253 public void removeToolbarMenu() { 254 255 } 256 257 @Override moveToPreviousFragment()258 public void moveToPreviousFragment() { 259 getSupportFragmentManager().popBackStack(); 260 } 261 262 /** 263 * Default implementation of intent factory that provides an intent to start an 264 * IndividualPickerActivity. 265 */ 266 public static class IndividualPickerActivityIntentFactory implements PickerIntentFactory { 267 @Override newIntent(Context ctx, String collectionId)268 public Intent newIntent(Context ctx, String collectionId) { 269 return new Intent(ctx, IndividualPickerActivity.class).putExtra( 270 EXTRA_CATEGORY_COLLECTION_ID, collectionId); 271 } 272 } 273 } 274