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