nxpandroid | 64fd68c | 2015-09-23 16:45:15 +0530 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2013 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.nfc.cardemulation; |
| 18 | |
| 19 | import com.android.internal.R; |
| 20 | import com.android.internal.app.AlertActivity; |
| 21 | import com.android.internal.app.AlertController; |
| 22 | |
| 23 | import java.util.ArrayList; |
| 24 | import java.util.List; |
| 25 | |
| 26 | import android.app.ActivityManager; |
| 27 | import android.content.BroadcastReceiver; |
| 28 | import android.content.ComponentName; |
| 29 | import android.content.Context; |
| 30 | import android.content.Intent; |
| 31 | import android.content.IntentFilter; |
| 32 | import android.content.pm.ApplicationInfo; |
| 33 | import android.content.pm.PackageManager; |
| 34 | import android.content.pm.PackageManager.NameNotFoundException; |
| 35 | import android.graphics.drawable.Drawable; |
| 36 | import android.nfc.NfcAdapter; |
| 37 | import android.nfc.cardemulation.ApduServiceInfo; |
| 38 | import android.nfc.cardemulation.CardEmulation; |
| 39 | import android.os.Bundle; |
| 40 | import android.util.Log; |
| 41 | import android.view.LayoutInflater; |
| 42 | import android.view.View; |
| 43 | import android.view.ViewGroup; |
| 44 | import android.view.Window; |
| 45 | import android.view.WindowManager; |
| 46 | import android.widget.AdapterView; |
| 47 | import android.widget.BaseAdapter; |
| 48 | import android.widget.ImageView; |
| 49 | import android.widget.ListView; |
| 50 | import android.widget.TextView; |
| 51 | |
| 52 | public class AppChooserActivity extends AlertActivity |
| 53 | implements AdapterView.OnItemClickListener { |
| 54 | |
| 55 | static final String TAG = "AppChooserActivity"; |
| 56 | |
| 57 | public static final String EXTRA_APDU_SERVICES = "services"; |
| 58 | public static final String EXTRA_CATEGORY = "category"; |
| 59 | public static final String EXTRA_FAILED_COMPONENT = "failed_component"; |
| 60 | |
| 61 | private int mIconSize; |
| 62 | private ListView mListView; |
| 63 | private ListAdapter mListAdapter; |
| 64 | private CardEmulation mCardEmuManager; |
| 65 | private String mCategory; |
| 66 | |
| 67 | final BroadcastReceiver mReceiver = new BroadcastReceiver() { |
| 68 | @Override |
| 69 | public void onReceive(Context context, Intent intent) { |
| 70 | finish(); |
| 71 | } |
| 72 | }; |
| 73 | |
| 74 | @Override |
| 75 | protected void onDestroy() { |
| 76 | super.onDestroy(); |
| 77 | unregisterReceiver(mReceiver); |
| 78 | } |
| 79 | |
| 80 | protected void onCreate(Bundle savedInstanceState, String category, |
| 81 | ArrayList<ApduServiceInfo> options, ComponentName failedComponent) { |
| 82 | super.onCreate(savedInstanceState); |
| 83 | setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert); |
| 84 | |
| 85 | IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); |
| 86 | registerReceiver(mReceiver, filter); |
| 87 | |
| 88 | if ((options == null || options.size() == 0) && failedComponent == null) { |
| 89 | Log.e(TAG, "No components passed in."); |
| 90 | finish(); |
| 91 | return; |
| 92 | } |
| 93 | |
| 94 | mCategory = category; |
| 95 | boolean isPayment = CardEmulation.CATEGORY_PAYMENT.equals(mCategory); |
| 96 | |
| 97 | final NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this); |
| 98 | mCardEmuManager = CardEmulation.getInstance(adapter); |
| 99 | AlertController.AlertParams ap = mAlertParams; |
| 100 | |
| 101 | final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE); |
| 102 | mIconSize = am.getLauncherLargeIconSize(); |
| 103 | |
| 104 | // Three cases: |
| 105 | // 1. Failed component and no alternatives: just an OK box |
| 106 | // 2. Failed component and alternatives: pick alternative |
| 107 | // 3. No failed component and alternatives: pick alternative |
| 108 | PackageManager pm = getPackageManager(); |
| 109 | |
| 110 | CharSequence applicationLabel = "unknown"; |
| 111 | if (failedComponent != null) { |
| 112 | try { |
| 113 | ApplicationInfo info = pm.getApplicationInfo(failedComponent.getPackageName(), 0); |
| 114 | applicationLabel = info.loadLabel(pm); |
| 115 | } catch (NameNotFoundException e) { |
| 116 | } |
| 117 | |
| 118 | } |
| 119 | if (options.size() == 0 && failedComponent != null) { |
| 120 | String formatString = getString(com.android.nfc.R.string.transaction_failure); |
| 121 | ap.mTitle = ""; |
| 122 | ap.mMessage = String.format(formatString, applicationLabel); |
| 123 | ap.mPositiveButtonText = getString(R.string.ok); |
| 124 | setupAlert(); |
| 125 | } else { |
| 126 | mListAdapter = new ListAdapter(this, options); |
| 127 | if (failedComponent != null) { |
| 128 | String formatString = getString(com.android.nfc.R.string.could_not_use_app); |
| 129 | ap.mTitle = String.format(formatString, applicationLabel); |
| 130 | ap.mNegativeButtonText = getString(R.string.cancel); |
| 131 | } else { |
| 132 | if (CardEmulation.CATEGORY_PAYMENT.equals(category)) { |
| 133 | ap.mTitle = getString(com.android.nfc.R.string.pay_with); |
| 134 | } else { |
| 135 | ap.mTitle = getString(com.android.nfc.R.string.complete_with); |
| 136 | } |
| 137 | } |
| 138 | ap.mView = getLayoutInflater().inflate(com.android.nfc.R.layout.cardemu_resolver, null); |
| 139 | |
| 140 | mListView = (ListView) ap.mView.findViewById(com.android.nfc.R.id.resolver_list); |
| 141 | if (isPayment) { |
| 142 | mListView.setDivider(getResources().getDrawable(android.R.color.transparent)); |
| 143 | int height = (int) (getResources().getDisplayMetrics().density * 16); |
| 144 | mListView.setDividerHeight(height); |
| 145 | } else { |
| 146 | mListView.setPadding(0, 0, 0, 0); |
| 147 | } |
| 148 | mListView.setAdapter(mListAdapter); |
| 149 | mListView.setOnItemClickListener(this); |
| 150 | |
| 151 | setupAlert(); |
| 152 | } |
| 153 | Window window = getWindow(); |
| 154 | window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); |
| 155 | } |
| 156 | |
| 157 | @Override |
| 158 | protected void onCreate(Bundle savedInstanceState) { |
| 159 | Intent intent = getIntent(); |
| 160 | ArrayList<ApduServiceInfo> services = intent.getParcelableArrayListExtra(EXTRA_APDU_SERVICES); |
| 161 | String category = intent.getStringExtra(EXTRA_CATEGORY); |
| 162 | ComponentName failedComponent = intent.getParcelableExtra(EXTRA_FAILED_COMPONENT); |
| 163 | onCreate(savedInstanceState, category, services, failedComponent); |
| 164 | } |
| 165 | |
| 166 | @Override |
| 167 | public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
| 168 | DisplayAppInfo info = (DisplayAppInfo) mListAdapter.getItem(position); |
| 169 | mCardEmuManager.setDefaultForNextTap(info.serviceInfo.getComponent()); |
| 170 | Intent dialogIntent = new Intent(this, TapAgainDialog.class); |
| 171 | dialogIntent.putExtra(TapAgainDialog.EXTRA_CATEGORY, mCategory); |
| 172 | dialogIntent.putExtra(TapAgainDialog.EXTRA_APDU_SERVICE, info.serviceInfo); |
| 173 | startActivity(dialogIntent); |
| 174 | finish(); |
| 175 | } |
| 176 | |
| 177 | final class DisplayAppInfo { |
| 178 | ApduServiceInfo serviceInfo; |
| 179 | CharSequence displayLabel; |
| 180 | Drawable displayIcon; |
| 181 | Drawable displayBanner; |
| 182 | |
| 183 | public DisplayAppInfo(ApduServiceInfo serviceInfo, CharSequence label, Drawable icon, |
| 184 | Drawable banner) { |
| 185 | this.serviceInfo = serviceInfo; |
| 186 | displayIcon = icon; |
| 187 | displayLabel = label; |
| 188 | displayBanner = banner; |
| 189 | } |
| 190 | } |
| 191 | |
| 192 | final class ListAdapter extends BaseAdapter { |
| 193 | private final LayoutInflater mInflater; |
| 194 | private final boolean mIsPayment; |
| 195 | private List<DisplayAppInfo> mList; |
| 196 | |
| 197 | public ListAdapter(Context context, ArrayList<ApduServiceInfo> services) { |
| 198 | mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
| 199 | // For each component, get the corresponding app name and icon |
| 200 | PackageManager pm = getPackageManager(); |
| 201 | mList = new ArrayList<DisplayAppInfo>(); |
| 202 | mIsPayment = CardEmulation.CATEGORY_PAYMENT.equals(mCategory); |
| 203 | for (ApduServiceInfo service : services) { |
| 204 | CharSequence label = service.getDescription(); |
| 205 | if (label == null) label = service.loadLabel(pm); |
| 206 | Drawable icon = service.loadIcon(pm); |
| 207 | Drawable banner = null; |
| 208 | if (mIsPayment) { |
| 209 | banner = service.loadBanner(pm); |
| 210 | if (banner == null) { |
| 211 | Log.e(TAG, "Not showing " + label + " because no banner specified."); |
| 212 | continue; |
| 213 | } |
| 214 | } |
| 215 | DisplayAppInfo info = new DisplayAppInfo(service, label, icon, banner); |
| 216 | mList.add(info); |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | @Override |
| 221 | public int getCount() { |
| 222 | return mList.size(); |
| 223 | } |
| 224 | |
| 225 | @Override |
| 226 | public Object getItem(int position) { |
| 227 | return mList.get(position); |
| 228 | } |
| 229 | |
| 230 | @Override |
| 231 | public long getItemId(int position) { |
| 232 | return position; |
| 233 | } |
| 234 | |
| 235 | @Override |
| 236 | public View getView(int position, View convertView, ViewGroup parent) { |
| 237 | View view; |
| 238 | if (convertView == null) { |
| 239 | if (mIsPayment) { |
| 240 | view = mInflater.inflate( |
| 241 | com.android.nfc.R.layout.cardemu_payment_item, parent, false); |
| 242 | } else { |
| 243 | view = mInflater.inflate( |
| 244 | com.android.nfc.R.layout.cardemu_item, parent, false); |
| 245 | } |
| 246 | final ViewHolder holder = new ViewHolder(view); |
| 247 | view.setTag(holder); |
| 248 | |
| 249 | } else { |
| 250 | view = convertView; |
| 251 | } |
| 252 | |
| 253 | final ViewHolder holder = (ViewHolder) view.getTag(); |
| 254 | DisplayAppInfo appInfo = mList.get(position); |
| 255 | if (mIsPayment) { |
| 256 | holder.banner.setImageDrawable(appInfo.displayBanner); |
| 257 | } else { |
| 258 | ViewGroup.LayoutParams lp = holder.icon.getLayoutParams(); |
| 259 | lp.width = lp.height = mIconSize; |
| 260 | holder.icon.setImageDrawable(appInfo.displayIcon); |
| 261 | holder.text.setText(appInfo.displayLabel); |
| 262 | } |
| 263 | return view; |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | static class ViewHolder { |
| 268 | public TextView text; |
| 269 | public ImageView icon; |
| 270 | public ImageView banner; |
| 271 | public ViewHolder(View view) { |
| 272 | text = (TextView) view.findViewById(com.android.nfc.R.id.applabel); |
| 273 | icon = (ImageView) view.findViewById(com.android.nfc.R.id.appicon); |
| 274 | banner = (ImageView) view.findViewById(com.android.nfc.R.id.banner); |
| 275 | } |
| 276 | } |
nxpandroid | 8aecbf8 | 2016-09-16 20:21:47 +0530 | [diff] [blame] | 277 | } |