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