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