1 /** 2 * Copyright (c) 2018 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 com.example.android.multidisplay.launcher; 18 19 import static com.example.android.multidisplay.launcher.PinnedAppListViewModel.PINNED_APPS_KEY; 20 21 import android.app.Application; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ResolveInfo; 27 import android.content.SharedPreferences; 28 import android.os.AsyncTask; 29 30 import androidx.lifecycle.AndroidViewModel; 31 import androidx.lifecycle.LiveData; 32 33 import java.util.ArrayList; 34 import java.util.List; 35 import java.util.Set; 36 37 /** 38 * A view model that provides a list of activities that were pinned by user to always display on 39 * home screen. 40 * The pinned activities are stored in {@link SharedPreferences} to keep the sample simple :). 41 */ 42 public class PinnedAppListViewModel extends AndroidViewModel { 43 44 final static String PINNED_APPS_KEY = "pinned_apps"; 45 46 private final PinnedAppListLiveData mLiveData; 47 PinnedAppListViewModel(Application application)48 public PinnedAppListViewModel(Application application) { 49 super(application); 50 mLiveData = new PinnedAppListLiveData(application); 51 } 52 getPinnedAppList()53 public LiveData<List<AppEntry>> getPinnedAppList() { 54 return mLiveData; 55 } 56 } 57 58 class PinnedAppListLiveData extends LiveData<List<AppEntry>> { 59 60 private final Context mContext; 61 private final PackageManager mPackageManager; 62 // Store listener reference, so it won't be GC-ed. 63 private final SharedPreferences.OnSharedPreferenceChangeListener mChangeListener; 64 private int mCurrentDataVersion; 65 PinnedAppListLiveData(Context context)66 public PinnedAppListLiveData(Context context) { 67 mContext = context; 68 mPackageManager = context.getPackageManager(); 69 70 final SharedPreferences prefs = context.getSharedPreferences(PINNED_APPS_KEY, 0); 71 mChangeListener = (preferences, key) -> { 72 loadData(); 73 }; 74 prefs.registerOnSharedPreferenceChangeListener(mChangeListener); 75 76 loadData(); 77 } 78 loadData()79 private void loadData() { 80 final int loadDataVersion = ++mCurrentDataVersion; 81 82 new AsyncTask<Void, Void, List<AppEntry>>() { 83 @Override 84 protected List<AppEntry> doInBackground(Void... voids) { 85 List<AppEntry> entries = new ArrayList<>(); 86 87 final SharedPreferences sp = mContext.getSharedPreferences(PINNED_APPS_KEY, 0); 88 final Set<String> pinnedAppsComponents = sp.getStringSet(PINNED_APPS_KEY, null); 89 if (pinnedAppsComponents == null) { 90 return null; 91 } 92 93 for (String componentString : pinnedAppsComponents) { 94 final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); 95 mainIntent.setComponent(ComponentName.unflattenFromString(componentString)); 96 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 97 98 final List<ResolveInfo> apps = mPackageManager.queryIntentActivities(mainIntent, 99 PackageManager.GET_META_DATA); 100 101 if (apps != null) { 102 for (ResolveInfo app : apps) { 103 final AppEntry entry = new AppEntry(app, mPackageManager); 104 entries.add(entry); 105 } 106 } 107 } 108 109 return entries; 110 } 111 112 @Override 113 protected void onPostExecute(List<AppEntry> data) { 114 if (mCurrentDataVersion == loadDataVersion) { 115 setValue(data); 116 } 117 } 118 }.execute(); 119 } 120 }