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