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 */ 16 package com.android.settings.nfc; 17 18 import android.app.AlertDialog; 19 import android.content.ActivityNotFoundException; 20 import android.content.Context; 21 import android.app.Dialog; 22 import android.content.DialogInterface; 23 import android.content.Intent; 24 import android.support.v7.preference.PreferenceViewHolder; 25 import android.util.Log; 26 import android.view.LayoutInflater; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.widget.BaseAdapter; 30 import android.widget.CompoundButton; 31 import android.widget.ImageView; 32 import android.widget.RadioButton; 33 34 import com.android.settings.R; 35 import com.android.settings.nfc.PaymentBackend.PaymentAppInfo; 36 import com.android.settingslib.CustomDialogPreference; 37 38 import java.util.List; 39 40 public class NfcPaymentPreference extends CustomDialogPreference implements 41 PaymentBackend.Callback, View.OnClickListener { 42 43 private static final String TAG = "NfcPaymentPreference"; 44 45 private final NfcPaymentAdapter mAdapter; 46 private final Context mContext; 47 private final LayoutInflater mLayoutInflater; 48 private final PaymentBackend mPaymentBackend; 49 50 // Fields below only modified on UI thread 51 private ImageView mSettingsButtonView; 52 NfcPaymentPreference(Context context, PaymentBackend backend)53 public NfcPaymentPreference(Context context, PaymentBackend backend) { 54 super(context, null); 55 mPaymentBackend = backend; 56 mContext = context; 57 backend.registerCallback(this); 58 mAdapter = new NfcPaymentAdapter(); 59 setDialogTitle(context.getString(R.string.nfc_payment_pay_with)); 60 mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 61 setWidgetLayoutResource(R.layout.preference_widget_gear); 62 63 refresh(); 64 } 65 66 @Override onBindViewHolder(PreferenceViewHolder view)67 public void onBindViewHolder(PreferenceViewHolder view) { 68 super.onBindViewHolder(view); 69 70 mSettingsButtonView = (ImageView) view.findViewById(R.id.settings_button); 71 mSettingsButtonView.setOnClickListener(this); 72 73 updateSettingsVisibility(); 74 } 75 76 /** 77 * MUST be called on UI thread. 78 */ refresh()79 public void refresh() { 80 List<PaymentAppInfo> appInfos = mPaymentBackend.getPaymentAppInfos(); 81 PaymentAppInfo defaultApp = mPaymentBackend.getDefaultApp(); 82 if (appInfos != null) { 83 PaymentAppInfo[] apps = appInfos.toArray(new PaymentAppInfo[appInfos.size()]); 84 mAdapter.updateApps(apps, defaultApp); 85 } 86 setTitle(R.string.nfc_payment_default); 87 if (defaultApp != null) { 88 setSummary(defaultApp.label); 89 } else { 90 setSummary(mContext.getString(R.string.nfc_payment_default_not_set)); 91 } 92 updateSettingsVisibility(); 93 } 94 95 @Override onPrepareDialogBuilder(AlertDialog.Builder builder, DialogInterface.OnClickListener listener)96 protected void onPrepareDialogBuilder(AlertDialog.Builder builder, 97 DialogInterface.OnClickListener listener) { 98 super.onPrepareDialogBuilder(builder, listener); 99 100 builder.setSingleChoiceItems(mAdapter, 0, listener); 101 } 102 103 @Override onPaymentAppsChanged()104 public void onPaymentAppsChanged() { 105 refresh(); 106 } 107 108 @Override onClick(View view)109 public void onClick(View view) { 110 PaymentAppInfo defaultAppInfo = mPaymentBackend.getDefaultApp(); 111 if (defaultAppInfo != null && defaultAppInfo.settingsComponent != null) { 112 Intent settingsIntent = new Intent(Intent.ACTION_MAIN); 113 settingsIntent.setComponent(defaultAppInfo.settingsComponent); 114 settingsIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 115 try { 116 mContext.startActivity(settingsIntent); 117 } catch (ActivityNotFoundException e) { 118 Log.e(TAG, "Settings activity not found."); 119 } 120 } 121 } 122 updateSettingsVisibility()123 void updateSettingsVisibility() { 124 if (mSettingsButtonView != null) { 125 PaymentAppInfo defaultApp = mPaymentBackend.getDefaultApp(); 126 if (defaultApp == null || defaultApp.settingsComponent == null) { 127 mSettingsButtonView.setVisibility(View.GONE); 128 } else { 129 mSettingsButtonView.setVisibility(View.VISIBLE); 130 131 } 132 } 133 } 134 135 class NfcPaymentAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener, 136 View.OnClickListener { 137 // Only modified on UI thread 138 private PaymentAppInfo[] appInfos; 139 NfcPaymentAdapter()140 public NfcPaymentAdapter() { 141 } 142 updateApps(PaymentAppInfo[] appInfos, PaymentAppInfo currentDefault)143 public void updateApps(PaymentAppInfo[] appInfos, PaymentAppInfo currentDefault) { 144 // Clone app infos, only add those with a banner 145 this.appInfos = appInfos; 146 notifyDataSetChanged(); 147 } 148 149 @Override getCount()150 public int getCount() { 151 return appInfos.length; 152 } 153 154 @Override getItem(int i)155 public PaymentAppInfo getItem(int i) { 156 return appInfos[i]; 157 } 158 159 @Override getItemId(int i)160 public long getItemId(int i) { 161 return appInfos[i].componentName.hashCode(); 162 } 163 164 @Override getView(int position, View convertView, ViewGroup parent)165 public View getView(int position, View convertView, ViewGroup parent) { 166 ViewHolder holder; 167 PaymentAppInfo appInfo = appInfos[position]; 168 if (convertView == null) { 169 convertView = mLayoutInflater.inflate( 170 R.layout.nfc_payment_option, parent, false); 171 holder = new ViewHolder(); 172 holder.imageView = (ImageView) convertView.findViewById(R.id.banner); 173 holder.radioButton = (RadioButton) convertView.findViewById(R.id.button); 174 convertView.setTag(holder); 175 } else { 176 holder = (ViewHolder) convertView.getTag(); 177 } 178 holder.imageView.setImageDrawable(appInfo.banner); 179 holder.imageView.setTag(appInfo); 180 holder.imageView.setContentDescription(appInfo.label); 181 holder.imageView.setOnClickListener(this); 182 183 // Prevent checked callback getting called on recycled views 184 holder.radioButton.setOnCheckedChangeListener(null); 185 holder.radioButton.setChecked(appInfo.isDefault); 186 holder.radioButton.setContentDescription(appInfo.label); 187 holder.radioButton.setOnCheckedChangeListener(this); 188 holder.radioButton.setTag(appInfo); 189 return convertView; 190 } 191 192 public class ViewHolder { 193 public ImageView imageView; 194 public RadioButton radioButton; 195 } 196 197 @Override onCheckedChanged(CompoundButton compoundButton, boolean b)198 public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 199 PaymentAppInfo appInfo = (PaymentAppInfo) compoundButton.getTag(); 200 makeDefault(appInfo); 201 } 202 203 @Override onClick(View view)204 public void onClick(View view) { 205 PaymentAppInfo appInfo = (PaymentAppInfo) view.getTag(); 206 makeDefault(appInfo); 207 } 208 makeDefault(PaymentAppInfo appInfo)209 void makeDefault(PaymentAppInfo appInfo) { 210 if (!appInfo.isDefault) { 211 mPaymentBackend.setDefaultPaymentApp(appInfo.componentName); 212 } 213 Dialog dialog = getDialog(); 214 if (dialog != null) 215 dialog.dismiss(); 216 } 217 } 218 } 219