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 */ 16package com.android.settings.nfc; 17 18import android.app.AlertDialog; 19import android.content.ActivityNotFoundException; 20import android.content.Context; 21import android.content.DialogInterface; 22import android.content.Intent; 23import android.preference.DialogPreference; 24import android.util.Log; 25import android.view.LayoutInflater; 26import android.view.View; 27import android.view.ViewGroup; 28import android.widget.BaseAdapter; 29import android.widget.CompoundButton; 30import android.widget.ImageView; 31import android.widget.RadioButton; 32import com.android.settings.R; 33import com.android.settings.nfc.PaymentBackend.PaymentAppInfo; 34 35import java.util.List; 36 37public 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 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 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 */ 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 93 protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { 94 super.onPrepareDialogBuilder(builder); 95 96 builder.setSingleChoiceItems(mAdapter, 0, this); 97 } 98 99 @Override 100 public void onPaymentAppsChanged() { 101 refresh(); 102 } 103 104 @Override 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 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 136 public NfcPaymentAdapter() { 137 } 138 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 146 public int getCount() { 147 return appInfos.length; 148 } 149 150 @Override 151 public PaymentAppInfo getItem(int i) { 152 return appInfos[i]; 153 } 154 155 @Override 156 public long getItemId(int i) { 157 return appInfos[i].componentName.hashCode(); 158 } 159 160 @Override 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 194 public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 195 PaymentAppInfo appInfo = (PaymentAppInfo) compoundButton.getTag(); 196 makeDefault(appInfo); 197 } 198 199 @Override 200 public void onClick(View view) { 201 PaymentAppInfo appInfo = (PaymentAppInfo) view.getTag(); 202 makeDefault(appInfo); 203 } 204 205 void makeDefault(PaymentAppInfo appInfo) { 206 if (!appInfo.isDefault) { 207 mPaymentBackend.setDefaultPaymentApp(appInfo.componentName); 208 } 209 getDialog().dismiss(); 210 } 211 } 212} 213