summaryrefslogtreecommitdiffstats
path: root/src/com/cyanogenmod/setupwizard/setup
diff options
context:
space:
mode:
authorcretin45 <cretin45@gmail.com>2015-01-15 16:04:44 -0800
committercretin45 <cretin45@gmail.com>2015-01-15 16:04:44 -0800
commit0328b87bf68f6389049991c68caa515f4230f95f (patch)
tree556b0a23df4bb849eada991b01f4861c651f25e8 /src/com/cyanogenmod/setupwizard/setup
downloadpackages_apps_SetupWizard-0328b87bf68f6389049991c68caa515f4230f95f.zip
packages_apps_SetupWizard-0328b87bf68f6389049991c68caa515f4230f95f.tar.gz
packages_apps_SetupWizard-0328b87bf68f6389049991c68caa515f4230f95f.tar.bz2
SetupWizard: Initial commit
Diffstat (limited to 'src/com/cyanogenmod/setupwizard/setup')
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/AbstractSetupData.java155
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/CMSetupWizardData.java59
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/ChooseDataSimPage.java267
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/CyanogenAccountPage.java83
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/DateTimePage.java464
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/FinishPage.java86
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/GmsAccountPage.java90
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/LocationSettingsPage.java194
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/MobileDataPage.java211
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/Page.java46
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/PageList.java44
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/SetupDataCallbacks.java31
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/SetupPage.java126
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/SimCardMissingPage.java72
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/WelcomePage.java148
-rw-r--r--src/com/cyanogenmod/setupwizard/setup/WifiSetupPage.java65
16 files changed, 2141 insertions, 0 deletions
diff --git a/src/com/cyanogenmod/setupwizard/setup/AbstractSetupData.java b/src/com/cyanogenmod/setupwizard/setup/AbstractSetupData.java
new file mode 100644
index 0000000..fed8732
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/AbstractSetupData.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+
+import java.util.ArrayList;
+
+public abstract class AbstractSetupData implements SetupDataCallbacks {
+
+ private static final String TAG = AbstractSetupData.class.getSimpleName();
+
+ protected Context mContext;
+ private ArrayList<SetupDataCallbacks> mListeners = new ArrayList<SetupDataCallbacks>();
+ private PageList mPageList;
+
+ private int mCurrentPageIndex = 0;
+
+ public AbstractSetupData(Context context) {
+ mContext = context;
+ mPageList = onNewPageList();
+ }
+
+ protected abstract PageList onNewPageList();
+
+ @Override
+ public void onPageLoaded(Page page) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onPageLoaded(page);
+ }
+ }
+
+ @Override
+ public void onPageTreeChanged() {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onPageTreeChanged();
+ }
+ }
+
+ @Override
+ public void onFinish() {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onFinish();
+ }
+ }
+
+ @Override
+ public Page getPage(String key) {
+ return mPageList.getPage(key);
+ }
+
+ @Override
+ public Page getPage(int index) {
+ return mPageList.getPage(index);
+ }
+
+ public Page getCurrentPage() {
+ return mPageList.getPage(mCurrentPageIndex);
+ }
+
+ public boolean isFirstPage() {
+ return mCurrentPageIndex == 0;
+ }
+
+ public boolean isLastPage() {
+ return mCurrentPageIndex == mPageList.size() - 1;
+ }
+
+ @Override
+ public void onNextPage() {
+ if (getCurrentPage().doNextAction() == false) {
+ if (advanceToNextUncompleted()) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onNextPage();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onPreviousPage() {
+ if (getCurrentPage().doPreviousAction() == false) {
+ if (advanceToPreviousUncompleted()) {
+ for (int i = 0; i < mListeners.size(); i++) {
+ mListeners.get(i).onPreviousPage();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onPageViewCreated(LayoutInflater inflater, Bundle savedInstanceState,
+ int layoutResource) {}
+
+ private boolean advanceToNextUncompleted() {
+ while (mCurrentPageIndex < mPageList.size()) {
+ mCurrentPageIndex++;
+ if (!getCurrentPage().isCompleted()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean advanceToPreviousUncompleted() {
+ while (mCurrentPageIndex > 0) {
+ mCurrentPageIndex--;
+ if (!getCurrentPage().isCompleted()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void load(Bundle savedValues) {
+ for (String key : savedValues.keySet()) {
+ Page page = mPageList.getPage(key);
+ if (page != null) {
+ page.resetData(savedValues.getBundle(key));
+ }
+ }
+ }
+
+ public Bundle save() {
+ Bundle bundle = new Bundle();
+ for (Page page : mPageList.values()) {
+ bundle.putBundle(page.getKey(), page.getData());
+ }
+ return bundle;
+ }
+
+ public void registerListener(SetupDataCallbacks listener) {
+ mListeners.add(listener);
+ }
+
+ public void unregisterListener(SetupDataCallbacks listener) {
+ mListeners.remove(listener);
+ }
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/CMSetupWizardData.java b/src/com/cyanogenmod/setupwizard/setup/CMSetupWizardData.java
new file mode 100644
index 0000000..e50f1ac
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/CMSetupWizardData.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
+
+import android.content.Context;
+import android.telephony.SubscriptionManager;
+
+import java.util.ArrayList;
+
+public class CMSetupWizardData extends AbstractSetupData {
+
+ public CMSetupWizardData(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected PageList onNewPageList() {
+ ArrayList<SetupPage> pages = new ArrayList<SetupPage>();
+ pages.add(new WelcomePage(mContext, this));
+ pages.add(new WifiSetupPage(mContext, this));
+ if (SetupWizardUtils.isGSMPhone(mContext) && SetupWizardUtils.isSimMissing(mContext)) {
+ pages.add(new SimCardMissingPage(mContext, this));
+ }
+ if (SetupWizardUtils.isMultiSimDevice(mContext)
+ && SubscriptionManager.getActiveSubInfoCount() > 1) {
+ pages.add(new ChooseDataSimPage(mContext, this));
+ }
+ if (SetupWizardUtils.hasTelephony(mContext) &&
+ !SetupWizardUtils.isMobileDataEnabled(mContext)) {
+ pages.add(new MobileDataPage(mContext, this));
+ }
+ if (SetupWizardUtils.hasGMS(mContext)) {
+ pages.add(new GmsAccountPage(mContext, this));
+ }
+ pages.add(new CyanogenAccountPage(mContext, this));
+ pages.add(new LocationSettingsPage(mContext, this));
+ pages.add(new DateTimePage(mContext, this));
+ pages.add(new FinishPage(mContext, this));
+ return new PageList(pages.toArray(new SetupPage[pages.size()]));
+ }
+
+
+} \ No newline at end of file
diff --git a/src/com/cyanogenmod/setupwizard/setup/ChooseDataSimPage.java b/src/com/cyanogenmod/setupwizard/setup/ChooseDataSimPage.java
new file mode 100644
index 0000000..820edc6
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/ChooseDataSimPage.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.SubInfoRecord;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
+
+import java.util.List;
+
+public class ChooseDataSimPage extends SetupPage {
+
+ public static final String TAG = "ChooseDataSimPage";
+
+ public ChooseDataSimPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public Fragment getFragment() {
+ Bundle args = new Bundle();
+ args.putString(SetupPage.KEY_PAGE_ARGUMENT, getKey());
+
+ ChooseDataSimFragment fragment = new ChooseDataSimFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_choose_data_sim;
+ }
+
+ @Override
+ public int getNextButtonTitleResId() {
+ return R.string.skip;
+ }
+
+
+ public static class ChooseDataSimFragment extends SetupPageFragment {
+
+ private ViewGroup mPageView;
+ private SparseArray<TextView> mNameViews;
+ private SparseArray<ImageView> mSignalViews;
+ private SparseArray<CheckBox> mCheckBoxes;
+
+ private TelephonyManager mPhone;
+ private List<SubInfoRecord> mSubInfoRecords;
+ private SparseArray<SignalStrength> mSignalStrengths;
+ private SparseArray<ServiceState> mServiceStates;
+ private SparseArray<PhoneStateListener> mPhoneStateListeners;
+
+ private View.OnClickListener mSetDataSimClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ SubInfoRecord subInfoRecord = (SubInfoRecord)view.getTag();
+ if (subInfoRecord != null) {
+ SubscriptionManager.setDefaultDataSubId(subInfoRecord.subId);
+ setDataSubChecked(subInfoRecord);
+ }
+ }
+ };
+
+ @Override
+ protected void initializePage() {
+ mPageView = (ViewGroup)mRootView.findViewById(R.id.page_view);
+ mSubInfoRecords = SubscriptionManager.getActiveSubInfoList();
+ int simCount = mSubInfoRecords.size();
+ mNameViews = new SparseArray<TextView>(simCount);
+ mSignalViews = new SparseArray<ImageView>(simCount);
+ mCheckBoxes = new SparseArray<CheckBox>(simCount);
+ mServiceStates = new SparseArray<ServiceState>(simCount);
+ mSignalStrengths = new SparseArray<SignalStrength>(simCount);
+ mPhoneStateListeners = new SparseArray<PhoneStateListener>(simCount);
+ LayoutInflater inflater = LayoutInflater.from(getActivity());
+ for (int i = 0; i < simCount; i++) {
+ View simRow = inflater.inflate(R.layout.data_sim_row, null);
+ mPageView.addView(simRow);
+ SubInfoRecord subInfoRecord = mSubInfoRecords.get(i);
+ simRow.setTag(subInfoRecord);
+ simRow.setOnClickListener(mSetDataSimClickListener);
+ mNameViews.put(i, (TextView) simRow.findViewById(R.id.sim_title));
+ mSignalViews.put(i, (ImageView) simRow.findViewById(R.id.signal));
+ mCheckBoxes.put(i, (CheckBox) simRow.findViewById(R.id.enable_check));
+ mPhoneStateListeners.put(i, createPhoneStateListener(subInfoRecord));
+ mPageView.addView(inflater.inflate(R.layout.divider, null));
+ }
+ mPhone = (TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE);
+ for (int i = 0; i < mPhoneStateListeners.size(); i++) {
+ mPhone.listen(mPhoneStateListeners.get(i),
+ PhoneStateListener.LISTEN_SERVICE_STATE
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+ }
+ updateSignalStrengths();
+ updateCurrentDataSub();
+ }
+
+ @Override
+ protected int getLayoutResource() {
+ return R.layout.choose_data_sim_page;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateSignalStrengths();
+ updateCurrentDataSub();
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ for (int i = 0; i < mPhoneStateListeners.size(); i++) {
+ mPhone.listen(mPhoneStateListeners.get(i), PhoneStateListener.LISTEN_NONE);
+ }
+ }
+
+ private PhoneStateListener createPhoneStateListener(final SubInfoRecord subInfoRecord) {
+ return new PhoneStateListener(subInfoRecord.subId) {
+
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ mSignalStrengths.put(subInfoRecord.slotId, signalStrength);
+ updateSignalStrength(subInfoRecord);
+ }
+
+ @Override
+ public void onServiceStateChanged(ServiceState state) {
+ mServiceStates.put(subInfoRecord.slotId, state);
+ updateSignalStrength(subInfoRecord);
+ }
+ };
+ }
+
+ private void updateSignalStrengths() {
+ for (int i = 0; i < mSubInfoRecords.size(); i++) {
+ updateSignalStrength(mSubInfoRecords.get(i));
+ }
+ }
+
+ private void setDataSubChecked(SubInfoRecord subInfoRecord) {
+ for (int i = 0; i < mCheckBoxes.size(); i++) {
+ mCheckBoxes.get(i).setChecked(subInfoRecord.slotId == i);
+
+ }
+ }
+
+ private void updateCurrentDataSub() {
+ for (int i = 0; i < mSubInfoRecords.size(); i++) {
+ SubInfoRecord subInfoRecord = mSubInfoRecords.get(i);
+ mCheckBoxes.get(i).setChecked(SubscriptionManager.getDefaultDataSubId()
+ == subInfoRecord.subId);
+
+ }
+ }
+
+ private void updateCarrierText(SubInfoRecord subInfoRecord) {
+ String name = mPhone.getNetworkOperatorName(subInfoRecord.subId);
+ ServiceState serviceState = mServiceStates.get(subInfoRecord.slotId);
+ if (TextUtils.isEmpty(name)) {
+ if (serviceState != null && serviceState.isEmergencyOnly()) {
+ name = getString(R.string.setup_mobile_data_emergency_only);
+ } else {
+ name = getString(R.string.setup_mobile_data_no_service);
+ }
+ }
+ String formattedName =
+ getString(R.string.data_sim_name, subInfoRecord.slotId + 1, name);
+ mNameViews.get(subInfoRecord.slotId).setText(formattedName);
+ }
+
+ private void updateSignalStrength(SubInfoRecord subInfoRecord) {
+ ImageView signalView = mSignalViews.get(subInfoRecord.slotId);
+ SignalStrength signalStrength = mSignalStrengths.get(subInfoRecord.slotId);
+ if (!hasService(subInfoRecord)) {
+ signalView.setImageResource(R.drawable.ic_signal_no_signal);
+ } else {
+ if (signalStrength != null) {
+ int resId;
+ switch (signalStrength.getLevel()) {
+ case 4:
+ resId = R.drawable.ic_signal_4;
+ break;
+ case 3:
+ resId = R.drawable.ic_signal_3;
+ break;
+ case 2:
+ resId = R.drawable.ic_signal_2;
+ break;
+ case 1:
+ resId = R.drawable.ic_signal_1;
+ break;
+ default:
+ resId = R.drawable.ic_signal_0;
+ break;
+ }
+ signalView.setImageResource(resId);
+ }
+ }
+ updateCarrierText(subInfoRecord);
+ }
+
+ private boolean hasService(SubInfoRecord subInfoRecord) {
+ boolean retVal;
+ ServiceState serviceState = mServiceStates.get(subInfoRecord.slotId);
+ if (serviceState != null) {
+ // Consider the device to be in service if either voice or data service is available.
+ // Some SIM cards are marketed as data-only and do not support voice service, and on
+ // these SIM cards, we want to show signal bars for data service as well as the "no
+ // service" or "emergency calls only" text that indicates that voice is not available.
+ switch(serviceState.getVoiceRegState()) {
+ case ServiceState.STATE_POWER_OFF:
+ retVal = false;
+ break;
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ case ServiceState.STATE_EMERGENCY_ONLY:
+ retVal = serviceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
+ break;
+ default:
+ retVal = true;
+ }
+ } else {
+ retVal = false;
+ }
+ Log.d(TAG, "hasService: mServiceState=" + serviceState + " retVal=" + retVal);
+ return retVal;
+ }
+ }
+
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/CyanogenAccountPage.java b/src/com/cyanogenmod/setupwizard/setup/CyanogenAccountPage.java
new file mode 100644
index 0000000..dc48faa
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/CyanogenAccountPage.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import com.cyanogenmod.setupwizard.SetupWizardApp;
+import com.cyanogenmod.setupwizard.R;
+
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+
+public class CyanogenAccountPage extends SetupPage {
+
+ public static final String TAG = "CyanogenAccountPage";
+
+ public CyanogenAccountPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public int getNextButtonTitleResId() {
+ return R.string.skip;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return -1;
+ }
+
+ @Override
+ public void doLoadAction(Activity context, int action) {
+ launchCyanogenAccountSetup(context, action);
+ }
+
+ public void launchCyanogenAccountSetup(final Activity activity, final int action) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SetupWizardApp.EXTRA_FIRST_RUN, true);
+ AccountManager
+ .get(activity).addAccount(SetupWizardApp.ACCOUNT_TYPE_CYANOGEN, null, null, bundle,
+ activity, new AccountManagerCallback<Bundle>() {
+ @Override
+ public void run(AccountManagerFuture<Bundle> bundleAccountManagerFuture) {
+ if (activity == null) return; //There is a chance this activity has been torn down.
+ if (accountExists(activity, SetupWizardApp.ACCOUNT_TYPE_CYANOGEN)) {
+ setCompleted(true);
+ getCallbacks().onNextPage();
+ } else {
+ if (action == Page.ACTION_NEXT) {
+ getCallbacks().onNextPage();
+ } else {
+ getCallbacks().onPreviousPage();
+ }
+ }
+ }
+ }, null);
+ }
+
+ private boolean accountExists(Activity activity, String accountType) {
+ return AccountManager.get(activity).getAccountsByType(accountType).length > 0;
+ }
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/DateTimePage.java b/src/com/cyanogenmod/setupwizard/setup/DateTimePage.java
new file mode 100644
index 0000000..40eda95
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/DateTimePage.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.DatePickerDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.TimePickerDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.XmlResourceParser;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.format.DateFormat;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.DatePicker;
+import android.widget.SimpleAdapter;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.TimePicker;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+public class DateTimePage extends SetupPage {
+
+ public static final String TAG = "DateTimePage";
+
+ private static final String KEY_ID = "id"; // value: String
+ private static final String KEY_DISPLAYNAME = "name"; // value: String
+ private static final String KEY_GMT = "gmt"; // value: String
+ private static final String KEY_OFFSET = "offset"; // value: int (Integer)
+ private static final String XMLTAG_TIMEZONE = "timezone";
+
+ private static final int HOURS_1 = 60 * 60000;
+
+
+ public DateTimePage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public Fragment getFragment() {
+ Bundle args = new Bundle();
+ args.putString(SetupPage.KEY_PAGE_ARGUMENT, getKey());
+
+ DateTimeFragment fragment = new DateTimeFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_datetime;
+ }
+
+ public static class DateTimeFragment extends SetupPageFragment
+ implements TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
+
+ private TimeZone mCurrentTimeZone;
+ private View mDateView;
+ private View mTimeView;
+ private TextView mDateTextView;
+ private TextView mTimeTextView;
+
+
+ private final Handler mHandler = new Handler();
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Register for time ticks and other reasons for time change
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_TIME_TICK);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ getActivity().registerReceiver(mIntentReceiver, filter, null, null);
+
+ updateTimeAndDateDisplay(getActivity());
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ getActivity().unregisterReceiver(mIntentReceiver);
+ }
+
+ @Override
+ protected void initializePage() {
+ final Spinner spinner = (Spinner) mRootView.findViewById(R.id.timezone_list);
+ final SimpleAdapter adapter = constructTimezoneAdapter(getActivity(), false);
+ mCurrentTimeZone = TimeZone.getDefault();
+ mDateView = mRootView.findViewById(R.id.date_item);
+ mDateView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showDatePicker();
+ }
+ });
+ mTimeView = mRootView.findViewById(R.id.time_item);
+ mTimeView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ showTimePicker();
+ }
+ });
+ mDateTextView = (TextView)mRootView.findViewById(R.id.date_text);
+ mTimeTextView = (TextView)mRootView.findViewById(R.id.time_text);
+ // Pre-select current/default timezone
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ int tzIndex = getTimeZoneIndex(adapter, mCurrentTimeZone);
+ spinner.setAdapter(adapter);
+ if (tzIndex != -1) {
+ spinner.setSelection(tzIndex);
+ }
+ spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
+ final Map<?, ?> map = (Map<?, ?>) adapterView.getItemAtPosition(position);
+ final String tzId = (String) map.get(KEY_ID);
+ if (mCurrentTimeZone != null && !mCurrentTimeZone.getID().equals(tzId)) {
+ // Update the system timezone value
+ final Activity activity = getActivity();
+ final AlarmManager alarm = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
+ alarm.setTimeZone(tzId);
+ mCurrentTimeZone = TimeZone.getTimeZone(tzId);
+ }
+
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> adapterView) {
+ }
+ });
+ }
+ });
+ }
+
+ private void showDatePicker() {
+ DatePickerFragment datePickerFragment = DatePickerFragment.newInstance();
+ datePickerFragment.setOnDateSetListener(this);
+ datePickerFragment.show(getFragmentManager(), DatePickerFragment.TAG);
+ }
+
+ private void showTimePicker() {
+ TimePickerFragment timePickerFragment = TimePickerFragment.newInstance();
+ timePickerFragment.setOnTimeSetListener(this);
+ timePickerFragment.show(getFragmentManager(), TimePickerFragment.TAG);
+ }
+
+ public void updateTimeAndDateDisplay(Context context) {
+ java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(context);
+ final Calendar now = Calendar.getInstance();
+ mTimeTextView.setText(DateFormat.getTimeFormat(getActivity()).format(now.getTime()));
+ mDateTextView.setText(shortDateFormat.format(now.getTime()));
+ }
+
+ @Override
+ protected int getLayoutResource() {
+ return R.layout.setup_datetime_page;
+ }
+
+ @Override
+ public void onDateSet(DatePicker view, int year, int month, int day) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ setDate(activity, year, month, day);
+ updateTimeAndDateDisplay(activity);
+ }
+ }
+
+ @Override
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ setTime(activity, hourOfDay, minute);
+ updateTimeAndDateDisplay(activity);
+ }
+ }
+
+ private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ updateTimeAndDateDisplay(activity);
+ }
+ }
+ };
+
+ }
+
+ private static SimpleAdapter constructTimezoneAdapter(Context context,
+ boolean sortedByName) {
+ final String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT};
+ final int[] to = new int[] {android.R.id.text1, android.R.id.text2};
+
+ final String sortKey = (sortedByName ? KEY_DISPLAYNAME : KEY_OFFSET);
+ final TimeZoneComparator comparator = new TimeZoneComparator(sortKey);
+ final List<HashMap<String, Object>> sortedList = getZones(context);
+ Collections.sort(sortedList, comparator);
+ final SimpleAdapter adapter = new SimpleAdapter(context,
+ sortedList,
+ R.layout.date_time_setup_custom_list_item_2,
+ from,
+ to);
+
+ return adapter;
+ }
+
+ private static List<HashMap<String, Object>> getZones(Context context) {
+ final List<HashMap<String, Object>> myData = new ArrayList<HashMap<String, Object>>();
+ final long date = Calendar.getInstance().getTimeInMillis();
+ try {
+ XmlResourceParser xrp = context.getResources().getXml(R.xml.timezones);
+ while (xrp.next() != XmlResourceParser.START_TAG)
+ continue;
+ xrp.next();
+ while (xrp.getEventType() != XmlResourceParser.END_TAG) {
+ while (xrp.getEventType() != XmlResourceParser.START_TAG) {
+ if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) {
+ return myData;
+ }
+ xrp.next();
+ }
+ if (xrp.getName().equals(XMLTAG_TIMEZONE)) {
+ String id = xrp.getAttributeValue(0);
+ String displayName = xrp.nextText();
+ addItem(myData, id, displayName, date);
+ }
+ while (xrp.getEventType() != XmlResourceParser.END_TAG) {
+ xrp.next();
+ }
+ xrp.next();
+ }
+ xrp.close();
+ } catch (XmlPullParserException xppe) {
+ Log.e(TAG, "Ill-formatted timezones.xml file");
+ } catch (java.io.IOException ioe) {
+ Log.e(TAG, "Unable to read timezones.xml file");
+ }
+
+ return myData;
+ }
+
+ private static void addItem(
+ List<HashMap<String, Object>> myData, String id, String displayName, long date) {
+ final HashMap<String, Object> map = new HashMap<String, Object>();
+ map.put(KEY_ID, id);
+ map.put(KEY_DISPLAYNAME, displayName);
+ final TimeZone tz = TimeZone.getTimeZone(id);
+ final int offset = tz.getOffset(date);
+ final int p = Math.abs(offset);
+ final StringBuilder name = new StringBuilder();
+ name.append("GMT");
+
+ if (offset < 0) {
+ name.append('-');
+ } else {
+ name.append('+');
+ }
+
+ name.append(p / (HOURS_1));
+ name.append(':');
+
+ int min = p / 60000;
+ min %= 60;
+
+ if (min < 10) {
+ name.append('0');
+ }
+ name.append(min);
+
+ map.put(KEY_GMT, name.toString());
+ map.put(KEY_OFFSET, offset);
+
+ myData.add(map);
+ }
+
+ private static int getTimeZoneIndex(SimpleAdapter adapter, TimeZone tz) {
+ final String defaultId = tz.getID();
+ final int listSize = adapter.getCount();
+ for (int i = 0; i < listSize; i++) {
+ // Using HashMap<String, Object> induces unnecessary warning.
+ final HashMap<?,?> map = (HashMap<?,?>)adapter.getItem(i);
+ final String id = (String)map.get(KEY_ID);
+ if (defaultId.equals(id)) {
+ // If current timezone is in this list, move focus to it
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private static void setDate(Context context, int year, int month, int day) {
+ Calendar c = Calendar.getInstance();
+
+ c.set(Calendar.YEAR, year);
+ c.set(Calendar.MONTH, month);
+ c.set(Calendar.DAY_OF_MONTH, day);
+ long when = c.getTimeInMillis();
+
+ if (when / 1000 < Integer.MAX_VALUE) {
+ ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
+ }
+ }
+
+ private static void setTime(Context context, int hourOfDay, int minute) {
+ Calendar c = Calendar.getInstance();
+
+ c.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ c.set(Calendar.MINUTE, minute);
+ c.set(Calendar.SECOND, 0);
+ c.set(Calendar.MILLISECOND, 0);
+ long when = c.getTimeInMillis();
+
+ if (when / 1000 < Integer.MAX_VALUE) {
+ ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
+ }
+ }
+
+ private static class TimeZoneComparator implements Comparator<HashMap<?, ?>> {
+ private String mSortingKey;
+
+ public TimeZoneComparator(String sortingKey) {
+ mSortingKey = sortingKey;
+ }
+
+ public void setSortingKey(String sortingKey) {
+ mSortingKey = sortingKey;
+ }
+
+ public int compare(HashMap<?, ?> map1, HashMap<?, ?> map2) {
+ Object value1 = map1.get(mSortingKey);
+ Object value2 = map2.get(mSortingKey);
+
+ /*
+ * This should never happen, but just in-case, put non-comparable
+ * items at the end.
+ */
+ if (!isComparable(value1)) {
+ return isComparable(value2) ? 1 : 0;
+ } else if (!isComparable(value2)) {
+ return -1;
+ }
+
+ return ((Comparable) value1).compareTo(value2);
+ }
+
+ private boolean isComparable(Object value) {
+ return (value != null) && (value instanceof Comparable);
+ }
+ }
+
+ private static class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener {
+
+ private static String TAG = TimePickerFragment.class.getSimpleName();
+
+ private TimePickerDialog.OnTimeSetListener mOnTimeSetListener;
+
+ public static TimePickerFragment newInstance() {
+ TimePickerFragment frag = new TimePickerFragment();
+ return frag;
+ }
+
+ private void setOnTimeSetListener(TimePickerDialog.OnTimeSetListener onTimeSetListener) {
+ mOnTimeSetListener = onTimeSetListener;
+ }
+
+ @Override
+ public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
+ if (mOnTimeSetListener != null) {
+ mOnTimeSetListener.onTimeSet(view, hourOfDay, minute);
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Calendar calendar = Calendar.getInstance();
+ return new TimePickerDialog(
+ getActivity(),
+ this,
+ calendar.get(Calendar.HOUR_OF_DAY),
+ calendar.get(Calendar.MINUTE),
+ DateFormat.is24HourFormat(getActivity()));
+
+ }
+ }
+
+ private static class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {
+
+ private static String TAG = DatePickerFragment.class.getSimpleName();
+
+ private DatePickerDialog.OnDateSetListener mOnDateSetListener;
+
+ public static DatePickerFragment newInstance() {
+ DatePickerFragment frag = new DatePickerFragment();
+ return frag;
+ }
+
+ private void setOnDateSetListener(DatePickerDialog.OnDateSetListener onDateSetListener) {
+ mOnDateSetListener = onDateSetListener;
+ }
+
+ @Override
+ public void onDateSet(DatePicker view, int year, int month, int day) {
+ if (mOnDateSetListener != null) {
+ mOnDateSetListener.onDateSet(view, year, month, day);
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Calendar calendar = Calendar.getInstance();
+ return new DatePickerDialog(
+ getActivity(),
+ this,
+ calendar.get(Calendar.YEAR),
+ calendar.get(Calendar.MONTH),
+ calendar.get(Calendar.DAY_OF_MONTH));
+
+ }
+ }
+
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/FinishPage.java b/src/com/cyanogenmod/setupwizard/setup/FinishPage.java
new file mode 100644
index 0000000..1ab0df9
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/FinishPage.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+
+public class FinishPage extends SetupPage {
+
+ public static final String TAG = "FinishPage";
+
+ public FinishPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public Fragment getFragment() {
+ Bundle args = new Bundle();
+ args.putString(SetupPage.KEY_PAGE_ARGUMENT, getKey());
+
+ FinishFragment fragment = new FinishFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_complete;
+ }
+
+ @Override
+ public boolean doNextAction() {
+ getCallbacks().onFinish();
+ return true;
+ }
+
+ @Override
+ public int getNextButtonTitleResId() {
+ return R.string.start;
+ }
+
+ @Override
+ public int getPrevButtonTitleResId() {
+ return -1;
+ }
+
+ public static class FinishFragment extends SetupPageFragment {
+
+ @Override
+ protected void initializePage() {}
+
+ @Override
+ protected int getLayoutResource() {
+ return R.layout.setup_finished_page;
+ }
+
+ @Override
+ protected int getHeaderLayoutResource() {
+ return -1;
+ }
+ }
+
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/GmsAccountPage.java b/src/com/cyanogenmod/setupwizard/setup/GmsAccountPage.java
new file mode 100644
index 0000000..a7d2aa8
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/GmsAccountPage.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.SetupWizardApp;
+
+import java.io.IOException;
+
+public class GmsAccountPage extends SetupPage {
+
+ public static final String TAG = "GmsAccountPage";
+
+ public GmsAccountPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_gms_account;
+ }
+
+ @Override
+ public int getNextButtonTitleResId() {
+ return R.string.skip;
+ }
+
+ @Override
+ public void doLoadAction(Activity context, int action) {
+ launchGmsAccountSetup(context, action);
+ }
+
+ public void launchGmsAccountSetup(final Activity activity, final int action) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SetupWizardApp.EXTRA_FIRST_RUN, true);
+ bundle.putBoolean(SetupWizardApp.EXTRA_ALLOW_SKIP, true);
+ AccountManager
+ .get(activity).addAccount(SetupWizardApp.ACCOUNT_TYPE_GMS, null, null,
+ bundle, activity, new AccountManagerCallback<Bundle>() {
+ @Override
+ public void run(AccountManagerFuture<Bundle> bundleAccountManagerFuture) {
+ //There is a chance this activity has been torn down.
+ if (activity == null) return;
+ String token = null;
+ try {
+ token = bundleAccountManagerFuture.getResult().getString(AccountManager.KEY_AUTHTOKEN);
+ } catch (OperationCanceledException e) {
+ } catch (IOException e) {
+ } catch (AuthenticatorException e) {
+ }
+ if (token != null) {
+ setCompleted(true);
+ }
+ if (action == Page.ACTION_NEXT) {
+ getCallbacks().onNextPage();
+ } else {
+ getCallbacks().onPreviousPage();
+ }
+ }
+ }, null);
+ }
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/LocationSettingsPage.java b/src/com/cyanogenmod/setupwizard/setup/LocationSettingsPage.java
new file mode 100644
index 0000000..00865f4
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/LocationSettingsPage.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.app.Fragment;
+import android.content.ContentQueryMap;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.view.View;
+import android.widget.CheckBox;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
+
+import java.util.Observable;
+import java.util.Observer;
+
+public class LocationSettingsPage extends SetupPage {
+
+ private static final String TAG = "LocationSettingsPage";
+
+ public LocationSettingsPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public Fragment getFragment() {
+ Bundle args = new Bundle();
+ args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
+
+ LocationSettingsFragment fragment = new LocationSettingsFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_location;
+ }
+
+ public static class LocationSettingsFragment extends SetupPageFragment {
+
+ private View mLocationRow;
+ private View mGpsRow;
+ private View mNetworkRow;
+ private CheckBox mNetwork;
+ private CheckBox mGps;
+ private CheckBox mLocationAccess;
+
+ private ContentResolver mContentResolver;
+
+ // These provide support for receiving notification when Location Manager settings change.
+ // This is necessary because the Network Location Provider can change settings
+ // if the user does not confirm enabling the provider.
+ private ContentQueryMap mContentQueryMap;
+ private Observer mSettingsObserver;
+
+
+ private View.OnClickListener mLocationClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ onToggleLocationAccess(!mLocationAccess.isChecked());
+ }
+ };
+
+ private View.OnClickListener mGpsClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Settings.Secure.setLocationProviderEnabled(mContentResolver,
+ LocationManager.GPS_PROVIDER, !mGps.isChecked());
+ }
+ };
+
+ private View.OnClickListener mNetworkClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Settings.Secure.setLocationProviderEnabled(mContentResolver,
+ LocationManager.NETWORK_PROVIDER, !mNetwork.isChecked());
+ }
+ };
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mContentResolver = getActivity().getContentResolver();
+ getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.primary_dark));
+ }
+
+ @Override
+ protected void initializePage() {
+ mLocationRow = mRootView.findViewById(R.id.location);
+ mLocationRow.setOnClickListener(mLocationClickListener);
+ mLocationAccess = (CheckBox) mRootView.findViewById(R.id.location_checkbox);
+ mGpsRow = mRootView.findViewById(R.id.gps);
+ mGpsRow.setOnClickListener(mGpsClickListener);
+ mGps = (CheckBox) mRootView.findViewById(R.id.gps_checkbox);
+ mNetworkRow = mRootView.findViewById(R.id.network);
+ mNetworkRow.setOnClickListener(mNetworkClickListener);
+ mNetwork = (CheckBox) mRootView.findViewById(R.id.network_checkbox);
+ }
+
+ @Override
+ protected int getLayoutResource() {
+ return R.layout.location_settings;
+ }
+
+ @Override
+ protected int getHeaderLayoutResource() {
+ return R.layout.header_condensed;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateLocationToggles();
+ if (mSettingsObserver == null) {
+ mSettingsObserver = new Observer() {
+ public void update(Observable o, Object arg) {
+ updateLocationToggles();
+ }
+ };
+ }
+
+ mContentQueryMap.addObserver(mSettingsObserver);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ // listen for Location Manager settings changes
+ Cursor settingsCursor = getActivity().getContentResolver().query(Settings.Secure.CONTENT_URI, null,
+ "(" + Settings.System.NAME + "=?)",
+ new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED},
+ null);
+ mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null);
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ if (mSettingsObserver != null) {
+ mContentQueryMap.deleteObserver(mSettingsObserver);
+ }
+ mContentQueryMap.close();
+ }
+
+
+ private void updateLocationToggles() {
+ boolean gpsEnabled = Settings.Secure.isLocationProviderEnabled(
+ mContentResolver, LocationManager.GPS_PROVIDER);
+ boolean networkEnabled = Settings.Secure.isLocationProviderEnabled(
+ mContentResolver, LocationManager.NETWORK_PROVIDER);
+ mGps.setChecked(gpsEnabled);
+ mNetwork.setChecked(networkEnabled);
+ mLocationAccess.setChecked(gpsEnabled || networkEnabled);
+ }
+
+ private void onToggleLocationAccess(boolean checked) {
+ Settings.Secure.setLocationProviderEnabled(mContentResolver,
+ LocationManager.GPS_PROVIDER, checked);
+ mGps.setEnabled(checked);
+ mGpsRow.setEnabled(checked);
+ Settings.Secure.setLocationProviderEnabled(mContentResolver,
+ LocationManager.NETWORK_PROVIDER, checked);
+ mNetwork.setEnabled(checked);
+ mNetworkRow.setEnabled(checked);
+ updateLocationToggles();
+ }
+
+ }
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/MobileDataPage.java b/src/com/cyanogenmod/setupwizard/setup/MobileDataPage.java
new file mode 100644
index 0000000..9223128
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/MobileDataPage.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
+import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
+
+public class MobileDataPage extends SetupPage {
+
+ public static final String TAG = "MobileDataPage";
+
+ public MobileDataPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public Fragment getFragment() {
+ Bundle args = new Bundle();
+ args.putString(SetupPage.KEY_PAGE_ARGUMENT, getKey());
+
+ MobileDataFragment fragment = new MobileDataFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_mobile_data;
+ }
+
+ public static class MobileDataFragment extends SetupPageFragment {
+
+ private View mEnableDataRow;
+ private Switch mEnableMobileData;
+ private ImageView mSignalView;
+ private TextView mNameView;
+
+ private TelephonyManager mPhone;
+ private SignalStrength mSignalStrength;
+ private ServiceState mServiceState;
+
+ private PhoneStateListener mPhoneStateListener =
+ new PhoneStateListener(SubscriptionManager.getDefaultDataSubId()) {
+
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ mSignalStrength = signalStrength;
+ updateSignalStrength();
+ }
+
+ @Override
+ public void onServiceStateChanged(ServiceState state) {
+ mServiceState = state;
+ updateSignalStrength();
+ }
+
+ };
+
+ private View.OnClickListener mEnableDataClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ boolean checked = !mEnableMobileData.isChecked();
+ SetupWizardUtils.setMobileDataEnabled(getActivity(), checked);
+ mEnableMobileData.setChecked(checked);
+ }
+ };
+
+ @Override
+ protected void initializePage() {
+ mEnableDataRow = mRootView.findViewById(R.id.data);
+ mEnableDataRow.setOnClickListener(mEnableDataClickListener);
+ mEnableMobileData = (Switch) mRootView.findViewById(R.id.data_switch);
+ mSignalView = (ImageView) mRootView.findViewById(R.id.signal);
+ mNameView = (TextView) mRootView.findViewById(R.id.enable_data_title);
+ updateDataConnectionStatus();
+ updateSignalStrength();
+ }
+
+ @Override
+ protected int getLayoutResource() {
+ return R.layout.mobile_data_settings;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateDataConnectionStatus();
+ updateSignalStrength();
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mPhone = (TelephonyManager)getActivity().getSystemService(Context.TELEPHONY_SERVICE);
+ mPhone.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_SERVICE_STATE
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mPhone.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ }
+
+ private void updateCarrierText() {
+ String name = mPhone.getNetworkOperatorName(SubscriptionManager.getDefaultDataSubId());
+ if (TextUtils.isEmpty(name)) {
+ if (mServiceState != null && mServiceState.isEmergencyOnly()) {
+ name = getString(R.string.setup_mobile_data_emergency_only);
+ } else {
+ name = getString(R.string.setup_mobile_data_no_service);
+ }
+ }
+ mNameView.setText(name);
+ }
+
+ private void updateSignalStrength() {
+ if (!hasService()) {
+ mSignalView.setImageResource(R.drawable.ic_signal_no_signal);
+ } else {
+ if (mSignalStrength != null) {
+ int resId;
+ switch (mSignalStrength.getLevel()) {
+ case 4:
+ resId = R.drawable.ic_signal_4;
+ break;
+ case 3:
+ resId = R.drawable.ic_signal_3;
+ break;
+ case 2:
+ resId = R.drawable.ic_signal_2;
+ break;
+ case 1:
+ resId = R.drawable.ic_signal_1;
+ break;
+ default:
+ resId = R.drawable.ic_signal_0;
+ break;
+ }
+ mSignalView.setImageResource(resId);
+ }
+ }
+ updateCarrierText();
+ }
+
+ private void updateDataConnectionStatus() {
+ mEnableMobileData.setChecked(SetupWizardUtils.isMobileDataEnabled(getActivity()));
+ }
+
+ private boolean hasService() {
+ boolean retVal;
+ if (mServiceState != null) {
+ // Consider the device to be in service if either voice or data service is available.
+ // Some SIM cards are marketed as data-only and do not support voice service, and on
+ // these SIM cards, we want to show signal bars for data service as well as the "no
+ // service" or "emergency calls only" text that indicates that voice is not available.
+ switch(mServiceState.getVoiceRegState()) {
+ case ServiceState.STATE_POWER_OFF:
+ retVal = false;
+ break;
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ case ServiceState.STATE_EMERGENCY_ONLY:
+ retVal = mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
+ break;
+ default:
+ retVal = true;
+ }
+ } else {
+ retVal = false;
+ }
+ return retVal;
+ }
+
+ }
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/Page.java b/src/com/cyanogenmod/setupwizard/setup/Page.java
new file mode 100644
index 0000000..31a02a7
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/Page.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+
+public interface Page {
+
+ public static final String KEY_PAGE_ARGUMENT = "key_arg";
+
+ public static final int ACTION_NEXT = 1;
+ public static final int ACTION_PREVIOUS = 2;
+
+ public String getKey();
+ public int getTitleResId();
+ public int getPrevButtonTitleResId();
+ public int getNextButtonTitleResId();
+ public Fragment getFragment();
+ public Bundle getData();
+ public void resetData(Bundle data);
+ public boolean isRequired();
+ public Page setRequired(boolean required);
+ public boolean isCompleted();
+ public void setCompleted(boolean completed);
+ public boolean doPreviousAction();
+ public boolean doNextAction();
+ public void doLoadAction(Activity context, int action);
+ public abstract boolean onActivityResult(int requestCode, int resultCode, Intent data);
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/PageList.java b/src/com/cyanogenmod/setupwizard/setup/PageList.java
new file mode 100644
index 0000000..6709d47
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/PageList.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import java.util.LinkedHashMap;
+
+public class PageList extends LinkedHashMap<String, Page> {
+
+ public PageList(Page... pages) {
+ for (Page page : pages) {
+ put(page.getKey(), page);
+ }
+ }
+
+ public Page getPage(String key) {
+ return get(key);
+ }
+
+ public Page getPage(int index) {
+ int i=0;
+ for (Page page : values()) {
+ if (i == index) {
+ return page;
+ }
+ i++;
+ }
+ return null;
+ }
+
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/SetupDataCallbacks.java b/src/com/cyanogenmod/setupwizard/setup/SetupDataCallbacks.java
new file mode 100644
index 0000000..2e787b4
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/SetupDataCallbacks.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+
+public interface SetupDataCallbacks {
+ void onNextPage();
+ void onPreviousPage();
+ void onPageLoaded(Page page);
+ void onPageTreeChanged();
+ void onFinish();
+ Page getPage(String key);
+ Page getPage(int key);
+ void onPageViewCreated(LayoutInflater inflater, Bundle savedInstanceState, int layoutResource);
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/SetupPage.java b/src/com/cyanogenmod/setupwizard/setup/SetupPage.java
new file mode 100644
index 0000000..c607857
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/SetupPage.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import com.cyanogenmod.setupwizard.R;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+
+public abstract class SetupPage implements Page {
+
+ private final SetupDataCallbacks mCallbacks;
+
+ private Bundle mData = new Bundle();
+ private boolean mRequired = false;
+ private boolean mCompleted = false;
+
+ protected final Context mContext;
+
+ protected SetupPage(Context context, SetupDataCallbacks callbacks) {
+ mContext = context;
+ mCallbacks = callbacks;
+ }
+
+ @Override
+ public Fragment getFragment() {
+ return null;
+ }
+
+ @Override
+ public int getPrevButtonTitleResId() {
+ return -1;
+ }
+
+ @Override
+ public int getNextButtonTitleResId() {
+ return R.string.next;
+ }
+
+ @Override
+ public boolean doNextAction() {
+ return false;
+ }
+
+ @Override
+ public boolean doPreviousAction() {
+ return false;
+ }
+
+ @Override
+ public void doLoadAction(Activity context, int action) {
+ if (context == null || context.isFinishing()) { return; }
+ final FragmentManager fragmentManager = context.getFragmentManager();
+ if (action == Page.ACTION_NEXT) {
+ FragmentTransaction transaction = fragmentManager.beginTransaction();
+ transaction.replace(R.id.content, getFragment(), getKey());
+ transaction.commit();
+ } else {
+ FragmentTransaction transaction = fragmentManager.beginTransaction();
+ transaction.replace(R.id.content, getFragment(), getKey());
+ transaction.commit();
+ }
+ }
+
+ @Override
+ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
+ return false;
+ }
+
+ @Override
+ public boolean isRequired() {
+ return mRequired;
+ }
+
+ @Override
+ public Page setRequired(boolean required) {
+ mRequired = required;
+ return this;
+ }
+
+ @Override
+ public boolean isCompleted() {
+ return mCompleted;
+ }
+
+ @Override
+ public void setCompleted(boolean completed) {
+ mCompleted = completed;
+ mCallbacks.onNextPage();
+ }
+
+ @Override
+ public Bundle getData() {
+ return mData;
+ }
+
+ @Override
+ public void resetData(Bundle data) {
+ mData = data;
+ mCallbacks.onPageLoaded(this);
+ }
+
+ protected SetupDataCallbacks getCallbacks() {
+ return mCallbacks;
+ }
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/SimCardMissingPage.java b/src/com/cyanogenmod/setupwizard/setup/SimCardMissingPage.java
new file mode 100644
index 0000000..8f74e24
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/SimCardMissingPage.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
+
+public class SimCardMissingPage extends SetupPage {
+
+ public static final String TAG = "SimCardMissingPage";
+
+ public SimCardMissingPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public Fragment getFragment() {
+ Bundle args = new Bundle();
+ args.putString(SetupPage.KEY_PAGE_ARGUMENT, getKey());
+
+ FinishFragment fragment = new FinishFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_sim_missing;
+ }
+
+ @Override
+ public int getNextButtonTitleResId() {
+ return R.string.skip;
+ }
+
+
+ public static class FinishFragment extends SetupPageFragment {
+
+ @Override
+ protected void initializePage() {}
+
+ @Override
+ protected int getLayoutResource() {
+ return R.layout.sim_missing_page;
+ }
+
+ }
+
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/WelcomePage.java b/src/com/cyanogenmod/setupwizard/setup/WelcomePage.java
new file mode 100644
index 0000000..ca3bf99
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/WelcomePage.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.ArrayAdapter;
+import android.widget.NumberPicker;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.ui.LocalePicker;
+import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
+
+import java.util.Locale;
+
+public class WelcomePage extends SetupPage {
+
+ public static final String TAG = "WelcomePage";
+
+ public WelcomePage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public Fragment getFragment() {
+ Bundle args = new Bundle();
+ args.putString(SetupPage.KEY_PAGE_ARGUMENT, getKey());
+
+ WelcomeFragment fragment = new WelcomeFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.setup_welcome;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getPrevButtonTitleResId() {
+ return R.string.emergency_call;
+ }
+
+ public static class WelcomeFragment extends SetupPageFragment {
+
+ private ArrayAdapter<com.android.internal.app.LocalePicker.LocaleInfo> mLocaleAdapter;
+ private Locale mInitialLocale;
+ private Locale mCurrentLocale;
+ private int[] mAdapterIndices;
+
+ private LocalePicker mLanguagePicker;
+
+ private final Handler mHandler = new Handler();
+
+ private final Runnable mUpdateLocale = new Runnable() {
+ public void run() {
+ if (mCurrentLocale != null) {
+ com.android.internal.app.LocalePicker.updateLocale(mCurrentLocale);
+ }
+ }
+ };
+
+ @Override
+ protected void initializePage() {
+ mLanguagePicker = (LocalePicker) mRootView.findViewById(R.id.locale_list);
+ loadLanguages();
+ }
+
+ private void loadLanguages() {
+ mLocaleAdapter = com.android.internal.app.LocalePicker.constructAdapter(getActivity(), R.layout.locale_picker_item, R.id.locale);
+ mInitialLocale = Locale.getDefault();
+ mCurrentLocale = mInitialLocale;
+ mAdapterIndices = new int[mLocaleAdapter.getCount()];
+ int currentLocaleIndex = 0;
+ String [] labels = new String[mLocaleAdapter.getCount()];
+ for (int i=0; i<mAdapterIndices.length; i++) {
+ com.android.internal.app.LocalePicker.LocaleInfo localLocaleInfo = mLocaleAdapter.getItem(i);
+ Locale localLocale = localLocaleInfo.getLocale();
+ if (localLocale.equals(mCurrentLocale)) {
+ currentLocaleIndex = i;
+ }
+ mAdapterIndices[i] = i;
+ labels[i] = localLocaleInfo.getLabel();
+ }
+ mLanguagePicker.setDisplayedValues(labels);
+ mLanguagePicker.setMaxValue(labels.length - 1);
+ mLanguagePicker.setValue(currentLocaleIndex);
+ mLanguagePicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+ mLanguagePicker.setOnValueChangedListener(new LocalePicker.OnValueChangeListener() {
+ public void onValueChange(LocalePicker picker, int oldVal, int newVal) {
+ setLocaleFromPicker();
+ }
+ });
+ }
+
+ private void setLocaleFromPicker() {
+ int i = mAdapterIndices[mLanguagePicker.getValue()];
+ final com.android.internal.app.LocalePicker.LocaleInfo localLocaleInfo = mLocaleAdapter.getItem(i);
+ onLocaleChanged(localLocaleInfo.getLocale());
+ }
+
+ private void onLocaleChanged(Locale paramLocale) {
+ Resources localResources = getActivity().getResources();
+ Configuration localConfiguration1 = localResources.getConfiguration();
+ Configuration localConfiguration2 = new Configuration();
+ localConfiguration2.locale = paramLocale;
+ localResources.updateConfiguration(localConfiguration2, null);
+ localResources.updateConfiguration(localConfiguration1, null);
+ mHandler.removeCallbacks(mUpdateLocale);
+ mCurrentLocale = paramLocale;
+ mHandler.postDelayed(mUpdateLocale, 1000);
+ }
+
+ @Override
+ protected int getLayoutResource() {
+ return R.layout.setup_welcome_page;
+ }
+
+ @Override
+ protected int getHeaderLayoutResource() {
+ return R.layout.logo_header;
+ }
+ }
+
+}
diff --git a/src/com/cyanogenmod/setupwizard/setup/WifiSetupPage.java b/src/com/cyanogenmod/setupwizard/setup/WifiSetupPage.java
new file mode 100644
index 0000000..705b932
--- /dev/null
+++ b/src/com/cyanogenmod/setupwizard/setup/WifiSetupPage.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2013 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cyanogenmod.setupwizard.setup;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import com.cyanogenmod.setupwizard.R;
+import com.cyanogenmod.setupwizard.SetupWizardApp;
+import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
+
+public class WifiSetupPage extends SetupPage {
+
+ public static final String TAG = "WifiSetupPage";
+
+ public WifiSetupPage(Context context, SetupDataCallbacks callbacks) {
+ super(context, callbacks);
+ }
+
+ @Override
+ public int getNextButtonTitleResId() {
+ return R.string.skip;
+ }
+
+ @Override
+ public String getKey() {
+ return TAG;
+ }
+
+ @Override
+ public int getTitleResId() {
+ return R.string.existing;
+ }
+
+ @Override
+ public void doLoadAction(Activity context, int action) {
+ if (action == Page.ACTION_PREVIOUS) {
+ getCallbacks().onPreviousPage();
+ } else {
+ SetupWizardUtils.launchWifiSetup(context);
+ }
+ }
+
+ @Override
+ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode != SetupWizardApp.REQUEST_CODE_SETUP_WIFI) return false;
+ getCallbacks().onNextPage();
+ return true;
+ }
+}