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 17 package com.android.settings.applications.appinfo; 18 19 import android.app.AlertDialog; 20 import android.content.Context; 21 import android.content.DialogInterface; 22 import android.content.Intent; 23 import android.content.pm.PackageManager; 24 import android.content.pm.ResolveInfo; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.os.UserHandle; 28 import android.support.annotation.VisibleForTesting; 29 import android.support.v7.preference.PreferenceScreen; 30 import android.text.TextUtils; 31 import android.view.Menu; 32 import android.view.MenuInflater; 33 import android.view.MenuItem; 34 import android.view.View; 35 import android.widget.Button; 36 37 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 38 import com.android.settings.R; 39 import com.android.settings.applications.AppStoreUtil; 40 import com.android.settings.applications.LayoutPreference; 41 import com.android.settings.core.BasePreferenceController; 42 import com.android.settings.overlay.FeatureFactory; 43 import com.android.settingslib.applications.AppUtils; 44 import com.android.settingslib.core.lifecycle.Lifecycle; 45 import com.android.settingslib.core.lifecycle.LifecycleObserver; 46 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu; 47 import com.android.settingslib.core.lifecycle.events.OnOptionsItemSelected; 48 import com.android.settingslib.core.lifecycle.events.OnPrepareOptionsMenu; 49 import com.android.settingslib.wrapper.PackageManagerWrapper; 50 51 import java.util.List; 52 53 public class InstantAppButtonsPreferenceController extends BasePreferenceController implements 54 LifecycleObserver, OnCreateOptionsMenu, OnPrepareOptionsMenu, OnOptionsItemSelected, 55 DialogInterface.OnClickListener { 56 57 private static final String KEY_INSTANT_APP_BUTTONS = "instant_app_buttons"; 58 private static final String META_DATA_DEFAULT_URI = "default-url"; 59 60 private final AppInfoDashboardFragment mParent; 61 private final String mPackageName; 62 private final PackageManagerWrapper mPackageManagerWrapper; 63 private String mLaunchUri; 64 private LayoutPreference mPreference; 65 private MenuItem mInstallMenu; 66 67 public InstantAppButtonsPreferenceController(Context context, AppInfoDashboardFragment parent, 68 String packageName, Lifecycle lifecycle) { 69 super(context, KEY_INSTANT_APP_BUTTONS); 70 mParent = parent; 71 mPackageName = packageName; 72 mPackageManagerWrapper = new PackageManagerWrapper(context.getPackageManager()); 73 mLaunchUri = getDefaultLaunchUri(); 74 if (lifecycle != null) { 75 lifecycle.addObserver(this); 76 } 77 } 78 79 @Override 80 public int getAvailabilityStatus() { 81 return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo) 82 ? AVAILABLE : DISABLED_FOR_USER; 83 } 84 85 @Override 86 public void displayPreference(PreferenceScreen screen) { 87 super.displayPreference(screen); 88 mPreference = (LayoutPreference) screen.findPreference(KEY_INSTANT_APP_BUTTONS); 89 initButtons(mPreference.findViewById(R.id.instant_app_button_container)); 90 } 91 92 @Override 93 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 94 if (!TextUtils.isEmpty(mLaunchUri)) { 95 menu.add(0, AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU, 2, R.string.install_text) 96 .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); 97 } 98 } 99 100 @Override 101 public boolean onOptionsItemSelected(MenuItem menuItem) { 102 if (menuItem.getItemId() == AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU) { 103 final Intent appStoreIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName); 104 if (appStoreIntent != null) { 105 mParent.startActivity(appStoreIntent); 106 } 107 return true; 108 } 109 return false; 110 } 111 112 @Override 113 public void onPrepareOptionsMenu(Menu menu) { 114 mInstallMenu = menu.findItem(AppInfoDashboardFragment.INSTALL_INSTANT_APP_MENU); 115 if (mInstallMenu != null) { 116 if (AppStoreUtil.getAppStoreLink(mContext, mPackageName) == null) { 117 mInstallMenu.setEnabled(false); 118 } 119 } 120 } 121 122 @Override 123 public void onClick(DialogInterface dialog, int which) { 124 FeatureFactory.getFactory(mContext).getMetricsFeatureProvider() 125 .action(mContext, MetricsEvent.ACTION_SETTINGS_CLEAR_INSTANT_APP, mPackageName); 126 mPackageManagerWrapper.deletePackageAsUser( 127 mPackageName, null, 0, UserHandle.myUserId()); 128 } 129 130 AlertDialog createDialog(int id) { 131 if (id == AppInfoDashboardFragment.DLG_CLEAR_INSTANT_APP) { 132 AlertDialog confirmDialog = new AlertDialog.Builder(mContext) 133 .setPositiveButton(R.string.clear_instant_app_data, this) 134 .setNegativeButton(R.string.cancel, null) 135 .setTitle(R.string.clear_instant_app_data) 136 .setMessage(mContext.getString(R.string.clear_instant_app_confirmation)) 137 .create(); 138 return confirmDialog; 139 } 140 return null; 141 } 142 143 private void initButtons(View view) { 144 final Button installButton = view.findViewById(R.id.install); 145 final Button clearDataButton = view.findViewById(R.id.clear_data); 146 final Button launchButton = view.findViewById(R.id.launch); 147 if (!TextUtils.isEmpty(mLaunchUri)) { 148 installButton.setVisibility(View.GONE); 149 final Intent intent = new Intent(Intent.ACTION_VIEW); 150 intent.addCategory(Intent.CATEGORY_BROWSABLE); 151 intent.setPackage(mPackageName); 152 intent.setData(Uri.parse(mLaunchUri)); 153 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 154 launchButton.setOnClickListener(v -> mParent.startActivity(intent)); 155 } else { 156 launchButton.setVisibility(View.GONE); 157 final Intent appStoreIntent = AppStoreUtil.getAppStoreLink(mContext, mPackageName); 158 if (appStoreIntent != null) { 159 installButton.setOnClickListener(v -> mParent.startActivity(appStoreIntent)); 160 } else { 161 installButton.setEnabled(false); 162 } 163 } 164 clearDataButton.setOnClickListener( 165 v -> mParent.showDialogInner(mParent.DLG_CLEAR_INSTANT_APP, 0)); 166 } 167 168 private String getDefaultLaunchUri() { 169 final PackageManager manager = mContext.getPackageManager(); 170 final Intent intent = new Intent(Intent.ACTION_MAIN); 171 intent.addCategory(Intent.CATEGORY_LAUNCHER); 172 intent.setPackage(mPackageName); 173 final List<ResolveInfo> infos = manager.queryIntentActivities( 174 intent, PackageManager.GET_META_DATA | PackageManager.MATCH_INSTANT); 175 for (ResolveInfo info : infos) { 176 final Bundle metaData = info.activityInfo.metaData; 177 if (metaData != null) { 178 final String launchUri = metaData.getString(META_DATA_DEFAULT_URI); 179 if (!TextUtils.isEmpty(launchUri)) { 180 return launchUri; 181 } 182 } 183 } 184 return null; 185 } 186 } 187