1/* 2 * Copyright (C) 2015 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.support.car.lenspicker; 17 18import android.app.Activity; 19import android.content.Intent; 20import android.content.SharedPreferences; 21import android.content.pm.PackageManager; 22import android.content.pm.ResolveInfo; 23import android.content.pm.ResolveInfo.DisplayNameComparator; 24import android.os.Bundle; 25import android.service.media.MediaBrowserService; 26import android.text.TextUtils; 27import android.util.Log; 28import android.view.View; 29 30import com.android.car.view.PagedListView; 31 32import java.util.ArrayList; 33import java.util.Collections; 34import java.util.HashMap; 35import java.util.List; 36 37/** 38 * An Activity to present the user with a list of applications that can be started for a given 39 * facet. 40 */ 41public class LensPickerActivity extends Activity implements LensPickerSelectionHandler { 42 private static final String TAG = "LensPickerActivity"; 43 private PackageManager mPackageManager; 44 private SharedPreferences mSharedPrefs; 45 46 private String mLastLaunchedFacetId; 47 private String mLastLaunchedPackageName; 48 private Intent mLastLaunchedIntent; 49 50 private PagedListView mPagedListView; 51 52 @Override 53 protected void onCreate(Bundle savedInstanceState) { 54 super.onCreate(savedInstanceState); 55 56 mPackageManager = getPackageManager(); 57 mSharedPrefs = LensPickerUtils.getFacetSharedPrefs(this); 58 59 setContentView(R.layout.lens_list); 60 mPagedListView = (PagedListView) findViewById(R.id.list_view); 61 // Set this to light mode, since the scroll bar buttons always appear 62 // on top of a dark scrim. 63 mPagedListView.setLightMode(); 64 65 findViewById(R.id.dismiss_area).setOnClickListener(new View.OnClickListener() { 66 @Override 67 public void onClick(View v) { 68 finish(); 69 } 70 }); 71 } 72 73 @Override 74 protected void onResume() { 75 super.onResume(); 76 77 Intent intent = getIntent(); 78 String[] categories = intent.getStringArrayExtra( 79 LensPickerConstants.EXTRA_FACET_CATEGORIES); 80 String[] packages = intent.getStringArrayExtra(LensPickerConstants.EXTRA_FACET_PACKAGES); 81 String facetId = intent.getStringExtra(LensPickerConstants.EXTRA_FACET_ID); 82 83 List<ResolveInfo> resolveInfos = getComponents(packages, categories); 84 85 if (resolveInfos != null && resolveInfos.size() == 1) { 86 // Directly launch the package rather than showing a list of 1. 87 ResolveInfo rInfo = resolveInfos.get(0); 88 String packageName = LensPickerUtils.getPackageName(rInfo); 89 Intent launchIntent = LensPickerUtils.getLaunchIntent(packageName, rInfo, 90 mPackageManager); 91 if (launchIntent != null) { 92 launch(facetId, packageName, launchIntent); 93 } else { 94 Log.e(TAG, "Failed to get launch intent for package" + packageName); 95 } 96 finish(); 97 return; 98 } 99 100 mPagedListView.setAdapter(new LensPickerAdapter(this, resolveInfos, facetId, 101 this /* LensPickerSelectionHandler */)); 102 } 103 104 @Override 105 protected void onPause() { 106 super.onPause(); 107 108 if (mLastLaunchedFacetId == null || mLastLaunchedPackageName == null 109 || mLastLaunchedIntent == null) { 110 return; 111 } 112 113 LensPickerUtils.saveLastLaunchedAppInfo(mSharedPrefs, mLastLaunchedFacetId, 114 mLastLaunchedPackageName, mLastLaunchedIntent); 115 } 116 117 private boolean isReclick(Intent intent, Intent oldIntent) { 118 String oldFacetId = oldIntent.getStringExtra(LensPickerConstants.EXTRA_FACET_ID); 119 String newFacetId = intent.getStringExtra(LensPickerConstants.EXTRA_FACET_ID); 120 return TextUtils.equals(oldFacetId, newFacetId); 121 } 122 123 @Override 124 protected void onNewIntent(Intent intent) { 125 Intent oldIntent = getIntent(); 126 setIntent(intent); 127 if (isReclick(intent, oldIntent)) { 128 finish(); 129 } 130 } 131 132 private ArrayList<ResolveInfo> getComponents(String[] packages, String[] categories) { 133 List<ResolveInfo> packageList = new ArrayList<>(); 134 if (packages != null) { 135 for (int i = 0; i < packages.length; i++) { 136 packageList.addAll(resolvePackage(packages[i])); 137 } 138 } 139 140 if (categories != null) { 141 for (int i = 0; i < categories.length; i++) { 142 packageList.addAll(resolveCategory(categories[i])); 143 144 if (categories[i].equals(Intent.CATEGORY_APP_MUSIC)) { 145 packageList.addAll(resolveMediaBrowserServices()); 146 } 147 } 148 } 149 150 // De-dupe the list based on package names 151 HashMap<String, ResolveInfo> dedupeList = new HashMap<>(); 152 for (ResolveInfo pkg : packageList) { 153 String packageName = LensPickerUtils.getPackageName(pkg); 154 if (!dedupeList.containsKey(packageName) || LensPickerUtils.isMediaService(pkg)) { 155 dedupeList.put(packageName, pkg); 156 } 157 } 158 159 ArrayList<ResolveInfo> filteredPackageList = new ArrayList<>(dedupeList.values()); 160 if (Log.isLoggable(TAG, Log.DEBUG)) { 161 printResolveInfo("before dedupe", packageList); 162 printResolveInfo("after dedupe", filteredPackageList); 163 } 164 165 // If presenting a category, alphabetize the list based on name. 166 if (categories != null) { 167 Collections.sort(filteredPackageList, new DisplayNameComparator(mPackageManager)); 168 } 169 170 171 return filteredPackageList; 172 } 173 174 private List<ResolveInfo> resolvePackage(String packageName) { 175 Intent intent = new Intent(); 176 intent.setPackage(packageName); 177 intent.setAction(Intent.ACTION_MAIN); 178 intent.addCategory(Intent.CATEGORY_LAUNCHER); 179 return mPackageManager.queryIntentActivities(intent, 0); 180 } 181 182 private List<ResolveInfo> resolveCategory(String category) { 183 Intent intent = new Intent(); 184 intent.setAction(Intent.ACTION_MAIN); 185 intent.addCategory(Intent.CATEGORY_LAUNCHER); 186 intent.addCategory(category); 187 return mPackageManager.queryIntentActivities(intent, 0); 188 } 189 190 private List<ResolveInfo> resolveMediaBrowserServices() { 191 Intent intent = new Intent(); 192 intent.setAction(MediaBrowserService.SERVICE_INTERFACE); 193 return mPackageManager.queryIntentServices(intent, PackageManager.GET_RESOLVED_FILTER); 194 } 195 196 private void printResolveInfo(String title, List<ResolveInfo> list) { 197 String names = ""; 198 for (ResolveInfo info : list) { 199 names += " " + LensPickerUtils.getPackageName(info); 200 } 201 Log.d(TAG, title + " resolve info name: " + names); 202 } 203 204 @Override 205 public void onActivitySelected(LensPickerItem item) { 206 Intent launchIntent = item.getLaunchIntent(); 207 launch(item.getFacetId(), launchIntent.getPackage(), launchIntent); 208 finish(); 209 } 210 211 private void launch(String facetId, String packageName, Intent launchIntent) { 212 // Save the information for the application that is about to be launched. 213 mLastLaunchedFacetId = facetId; 214 mLastLaunchedPackageName = packageName; 215 mLastLaunchedIntent = launchIntent; 216 217 LensPickerUtils.launch(this /* context */, mSharedPrefs, facetId, packageName, 218 launchIntent); 219 } 220} 221