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