SetupWizard: Add Cyanogen services page

Change-Id: I39970b1b659a3a7ed3bb5b4350707aa0e53aba24
This commit is contained in:
cretin45 2015-01-19 14:29:43 -08:00
parent 74ca6faf3a
commit 48ca24eb9b
18 changed files with 625 additions and 100 deletions

View File

@ -5,7 +5,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
LOCAL_PACKAGE_NAME := CMSetupWizard LOCAL_PACKAGE_NAME := CyanogenSetupWizard
LOCAL_CERTIFICATE := platform LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true LOCAL_PRIVILEGED_MODULE := true

View File

@ -16,7 +16,8 @@
--> -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyanogenmod.setupwizard" package="com.cyanogenmod.setupwizard"
android:versionCode="3"> android:versionCode="3"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" /> <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.STATUS_BAR" /> <uses-permission android:name="android.permission.STATUS_BAR" />
@ -39,6 +40,21 @@
<uses-permission android:name="android.permission.ACCESS_THEME_MANAGER"/> <uses-permission android:name="android.permission.ACCESS_THEME_MANAGER"/>
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /> <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.HARDWARE_ABSTRACTION_ACCESS" /> <uses-permission android:name="android.permission.HARDWARE_ABSTRACTION_ACCESS" />
<uses-permission android:name="org.whispersystems.whisperpush.permissions.REGISTER" />
<permission
android:name="cyanogenmod.permission.PROTECTED_APP"
android:protectionLevel="signatureOrSystem" />
<permission
android:name="cyanogenmod.permission.FINISH_SETUP"
android:protectionLevel="signatureOrSystem" />
<permission android:name="org.whispersystems.whisperpush.permissions.REGISTER"
android:protectionLevel="signature" />
<protected-broadcast android:name="com.cyanogenmod.setupwizard.SETUP_FINISHED"
android:permission="cyanogenmod.permission.FINISH_SETUP"/>
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" /> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
@ -47,6 +63,8 @@
android:theme="@style/Theme.Setup" android:theme="@style/Theme.Setup"
android:name=".SetupWizardApp"> android:name=".SetupWizardApp">
<uses-library android:name="org.cyanogenmod.hardware" android:required="false" />
<meta-data android:name="com.google.android.gms.version" <meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" /> android:value="@integer/google_play_services_version" />

View File

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 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.
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/PageContent">
<!-- The caption about privacy policy -->
<TextView
android:id="@+id/privacy_policy"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="15sp"
android:layout_marginBottom="@dimen/summary_margin_bottom"
style="@style/PageSummaryText"
android:text="@string/services_explanation"
android:clickable="true"/>
<!-- Whether or not to enable metrics -->
<LinearLayout
android:id="@+id/metrics"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/location_margin_left"
android:layout_marginRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<CheckBox
android:id="@+id/enable_metrics_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="5dp"
android:duplicateParentState="true"
android:clickable="false"/>
<TextView
android:id="@+id/enable_metrics_summary"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="15sp"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom"
android:text="@string/services_metrics_label"
android:maxLines="5" />
</LinearLayout>
<!-- Checkbox for using on-screen nav keys -->
<LinearLayout
android:id="@+id/nav_keys"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/location_margin_left"
android:layout_marginRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<CheckBox
android:id="@+id/nav_keys_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="5dp"
android:duplicateParentState="true"
android:clickable="false" />
<TextView
android:id="@+id/nav_keys_summary"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="15sp"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom"
android:text="@string/services_os_nav_keys_label"
android:maxLines="5" />
</LinearLayout>
<!-- Checkbox for enabling secure SMS -->
<LinearLayout
android:id="@+id/secure_sms"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/location_margin_left"
android:layout_marginRight="@dimen/content_margin_right"
android:background="?android:attr/selectableItemBackground"
android:clickable="true">
<CheckBox
android:id="@+id/secure_sms_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="5dp"
android:duplicateParentState="true"
android:clickable="false" />
<TextView
android:id="@+id/secure_sms_summary"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="15sp"
android:gravity="top"
android:layout_marginLeft="@dimen/location_text_margin_left"
android:layout_marginRight="@dimen/location_text_margin_right"
android:paddingBottom="@dimen/content_margin_bottom"
android:text="@string/services_secure_sms_label"
android:maxLines="5" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@ -51,7 +51,7 @@
<string name="location_services_summary">Location services allows Maps and other apps to gather and use data such as your approximate location. For example, Maps may use your approximate location to locate nearby coffee shops.</string> <string name="location_services_summary">Location services allows Maps and other apps to gather and use data such as your approximate location. For example, Maps may use your approximate location to locate nearby coffee shops.</string>
<string name="location_access_summary">Allow apps that have asked your permission to use your location information. This may include your current location and past locations.</string> <string name="location_access_summary">Allow apps that have asked your permission to use your location information. This may include your current location and past locations.</string>
<string name="location_gps">Improve location accuracy by allowing apps to use the GPS on your phone.</string> <string name="location_gps">Improve location accuracy by allowing apps to use the GPS on your phone.</string>
<string name="location_network">Use Googles location service to help apps determine your location. This means sending annonymous location data to Google, even when no apps are running.</string> <string name="location_network">Use Google\'s location service to help apps determine your location. This means sending annonymous location data to Google, even when no apps are running.</string>
<string name="setup_mobile_data">Turn On Mobile Data</string> <string name="setup_mobile_data">Turn On Mobile Data</string>
<string name="setup_mobile_data_no_service">No service</string> <string name="setup_mobile_data_no_service">No service</string>
@ -63,4 +63,11 @@
<string name="data_sim_name">SIM <xliff:g id="sub">%d</xliff:g> - <xliff:g id="name">%s</xliff:g></string> <string name="data_sim_name">SIM <xliff:g id="sub">%d</xliff:g> - <xliff:g id="name">%s</xliff:g></string>
<string name="emergency_call">Emergency Call</string> <string name="emergency_call">Emergency Call</string>
<string name="setup_services">Cyanogen services</string>
<string name="services_explanation">These services work for you to extend the capabilities of your device. You can turn them off at anytime. Data will be used in accordance with Cyanogen\'s %s.</string>
<string name="services_privacy_policy">Privacy Policy</string>
<string name="services_metrics_label"><b>Help improve Cyanogen OS</b> by automatically sending diagnostic and usage data to Cyanogen. This information wont be used to identify you and lends a hand to teams working on things like battery life, app performance, and new Cyanogen OS features.</string>
<string name="services_os_nav_keys_label"><b>Use on screen navigation keys</b> to move between screens instead of hardware keys.</string>
<string name="services_secure_sms_label"><b>Use secure SMS</b> to encrypt SMS conversations with other users using secure SMS on a Cyanogen OS device.</string>
</resources> </resources>

View File

@ -27,6 +27,8 @@ public class SetupWizardApp extends Application {
// Leave this off for release // Leave this off for release
public static final boolean DEBUG = false; public static final boolean DEBUG = false;
public static final String ACTION_FINISHED = "com.cyanogenmod.setupwizard.SETUP_FINISHED";
public static final String ACCOUNT_TYPE_CYANOGEN = "com.cyanogen"; public static final String ACCOUNT_TYPE_CYANOGEN = "com.cyanogen";
public static final String ACCOUNT_TYPE_GMS = "com.google"; public static final String ACCOUNT_TYPE_GMS = "com.google";

View File

@ -48,7 +48,7 @@ public class CMSetupWizardData extends AbstractSetupData {
if (SetupWizardUtils.hasGMS(mContext)) { if (SetupWizardUtils.hasGMS(mContext)) {
pages.add(new GmsAccountPage(mContext, this)); pages.add(new GmsAccountPage(mContext, this));
} }
pages.add(new CyanogenAccountPage(mContext, this)); pages.add(new CyanogenServicesPage(mContext, this));
pages.add(new LocationSettingsPage(mContext, this)); pages.add(new LocationSettingsPage(mContext, this));
pages.add(new DateTimePage(mContext, this)); pages.add(new DateTimePage(mContext, this));
pages.add(new FinishPage(mContext, this)); pages.add(new FinishPage(mContext, this));

View File

@ -1,83 +0,0 @@
/*
* 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;
}
}

View File

@ -0,0 +1,307 @@
/*
* 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.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.IWindowManager;
import android.view.View;
import android.view.WindowManagerGlobal;
import android.widget.CheckBox;
import android.widget.TextView;
import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.ui.SetupPageFragment;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import org.cyanogenmod.hardware.KeyDisabler;
public class CyanogenServicesPage extends SetupPage {
public static final String TAG = "CyanogenServicesPage";
public static final String KEY_SEND_METRICS = "send_metrics";
public static final String KEY_REGISTER_WHISPERPUSH = "register";
public static final String SETTING_METRICS = "settings.cyanogen.allow_metrics";
public CyanogenServicesPage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks);
}
@Override
public Fragment getFragment() {
Bundle args = new Bundle();
args.putString(Page.KEY_PAGE_ARGUMENT, getKey());
CyanogenServicesFragment fragment = new CyanogenServicesFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public String getKey() {
return TAG;
}
@Override
public int getTitleResId() {
return R.string.setup_services;
}
private static void writeDisableNavkeysOption(Context context, boolean enabled) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final int defaultBrightness = context.getResources().getInteger(
com.android.internal.R.integer.config_buttonBrightnessSettingDefault);
Settings.System.putInt(context.getContentResolver(),
Settings.System.DEV_FORCE_SHOW_NAVBAR, enabled ? 1 : 0);
KeyDisabler.setActive(enabled);
/* Save/restore button timeouts to disable them in softkey mode */
SharedPreferences.Editor editor = prefs.edit();
if (enabled) {
int currentBrightness = Settings.System.getInt(context.getContentResolver(),
Settings.System.BUTTON_BRIGHTNESS, defaultBrightness);
if (!prefs.contains("pre_navbar_button_backlight")) {
editor.putInt("pre_navbar_button_backlight", currentBrightness);
}
Settings.System.putInt(context.getContentResolver(),
Settings.System.BUTTON_BRIGHTNESS, 0);
} else {
int oldBright = prefs.getInt("pre_navbar_button_backlight", -1);
if (oldBright != -1) {
Settings.System.putInt(context.getContentResolver(),
Settings.System.BUTTON_BRIGHTNESS, oldBright);
editor.remove("pre_navbar_button_backlight");
}
}
editor.commit();
}
private static boolean hideKeyDisabler() {
try {
return !KeyDisabler.isSupported();
} catch (NoClassDefFoundError e) {
// Hardware abstraction framework not installed
return true;
}
}
private static boolean hideWhisperPush(Context context) {
final int playServicesAvailable = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(context);
return playServicesAvailable != ConnectionResult.SUCCESS
|| (SetupWizardUtils.isGSMPhone(context) && SetupWizardUtils.isSimMissing(context));
}
public static class CyanogenServicesFragment extends SetupPageFragment {
private View mMetricsRow;
private View mNavKeysRow;
private View mSecureSmsRow;
private CheckBox mMetrics;
private CheckBox mNavKeys;
private CheckBox mSecureSms;
private Runnable mDeferredAction;
private Handler mHandler;
private View.OnClickListener mMetricsClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean checked = !mMetrics.isChecked();
mMetrics.setChecked(checked);
mPage.getData().putBoolean(KEY_SEND_METRICS, checked);
}
};
private View.OnClickListener mNavKeysClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
mNavKeys.setEnabled(false);
boolean checked = !mNavKeys.isChecked();
writeDisableNavkeysOption(getActivity(), checked);
updateDisableNavkeysOption();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mNavKeys.setEnabled(true);
}
}, 1000);
}
};
private View.OnClickListener mSecureSmsClickListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
boolean checked = !mSecureSms.isChecked();
mSecureSms.setChecked(checked);
mPage.getData().putBoolean(KEY_REGISTER_WHISPERPUSH, checked);
}
};
public CyanogenServicesFragment() {
super();
mHandler = new Handler();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.primary_dark));
if (!SetupWizardUtils.accountExists(getActivity(),
SetupWizardApp.ACCOUNT_TYPE_CYANOGEN)) {
launchCyanogenAccountSetup(getActivity());
}
}
@Override
protected void initializePage() {
String privacy_policy = getString(R.string.services_privacy_policy);
String summary = getString(R.string.services_explanation, privacy_policy);
SpannableString ss = new SpannableString(summary);
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View textView) {
//TDB privacy policy
}
};
ss.setSpan(clickableSpan,
summary.length() - privacy_policy.length() - 1,
summary.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView textView = (TextView) mRootView.findViewById(R.id.privacy_policy);
textView.setMovementMethod(LinkMovementMethod.getInstance());
textView.setText(ss);
mMetricsRow = mRootView.findViewById(R.id.metrics);
mMetricsRow.setOnClickListener(mMetricsClickListener);
mMetrics = (CheckBox) mRootView.findViewById(R.id.enable_metrics_checkbox);
boolean metricsChecked =
!mPage.getData().containsKey(KEY_SEND_METRICS) || mPage.getData()
.getBoolean(KEY_SEND_METRICS);
mMetrics.setChecked(metricsChecked);
mPage.getData().putBoolean(KEY_SEND_METRICS, metricsChecked);
mNavKeysRow = mRootView.findViewById(R.id.nav_keys);
mNavKeysRow.setOnClickListener(mNavKeysClickListener);
mNavKeys = (CheckBox) mRootView.findViewById(R.id.nav_keys_checkbox);
boolean needsNavBar = true;
try {
IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService();
needsNavBar = windowManager.needsNavigationBar();
} catch (RemoteException e) {
}
if (hideKeyDisabler() || needsNavBar) {
mNavKeysRow.setVisibility(View.GONE);
} else {
boolean navKeysDisabled =
KeyDisabler.isActive();
mNavKeys.setChecked(navKeysDisabled);
}
mSecureSmsRow = mRootView.findViewById(R.id.secure_sms);
mSecureSmsRow.setOnClickListener(mSecureSmsClickListener);
if (hideWhisperPush(getActivity())) {
mSecureSmsRow.setVisibility(View.GONE);
}
mSecureSms = (CheckBox) mRootView.findViewById(R.id.secure_sms_checkbox);
boolean smsChecked = mPage.getData().containsKey(KEY_REGISTER_WHISPERPUSH) ?
mPage.getData().getBoolean(KEY_REGISTER_WHISPERPUSH) :
false;
mSecureSms.setChecked(smsChecked);
mPage.getData().putBoolean(KEY_REGISTER_WHISPERPUSH, smsChecked);
}
@Override
protected int getLayoutResource() {
return R.layout.setup_cyanogen_services;
}
@Override
protected int getHeaderLayoutResource() {
return R.layout.header_condensed;
}
@Override
public void onResume() {
super.onResume();
updateDisableNavkeysOption();
runDeferredAction();
}
private void runDeferredAction() {
if (mDeferredAction != null) {
mDeferredAction.run();
mDeferredAction = null;
}
}
private void updateDisableNavkeysOption() {
boolean enabled = Settings.System.getInt(getActivity().getContentResolver(),
Settings.System.DEV_FORCE_SHOW_NAVBAR, 0) != 0;
mNavKeys.setChecked(enabled);
}
private void launchCyanogenAccountSetup(final Activity activity) {
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.
Runnable runnable = new Runnable() {
@Override
public void run() {
if (!SetupWizardUtils.accountExists(activity,
SetupWizardApp.ACCOUNT_TYPE_CYANOGEN)) {
mPage.getCallbacks().onNextPage();
}
}
};
if (activity.isResumed()) {
runnable.run();
} else {
mDeferredAction = runnable;
}
}
}, null);
}
}
}

View File

@ -55,10 +55,14 @@ public class GmsAccountPage extends SetupPage {
@Override @Override
public void doLoadAction(Activity context, int action) { public void doLoadAction(Activity context, int action) {
launchGmsAccountSetup(context, action); if (action == Page.ACTION_PREVIOUS) {
getCallbacks().onPreviousPage();
} else {
launchGmsAccountSetup(context);
}
} }
public void launchGmsAccountSetup(final Activity activity, final int action) { public void launchGmsAccountSetup(final Activity activity) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putBoolean(SetupWizardApp.EXTRA_FIRST_RUN, true); bundle.putBoolean(SetupWizardApp.EXTRA_FIRST_RUN, true);
bundle.putBoolean(SetupWizardApp.EXTRA_ALLOW_SKIP, true); bundle.putBoolean(SetupWizardApp.EXTRA_ALLOW_SKIP, true);
@ -79,11 +83,7 @@ public class GmsAccountPage extends SetupPage {
if (token != null) { if (token != null) {
setCompleted(true); setCompleted(true);
} }
if (action == Page.ACTION_NEXT) {
getCallbacks().onNextPage(); getCallbacks().onNextPage();
} else {
getCallbacks().onPreviousPage();
}
} }
}, null); }, null);
} }

View File

@ -42,5 +42,6 @@ public interface Page {
public boolean doPreviousAction(); public boolean doPreviousAction();
public boolean doNextAction(); public boolean doNextAction();
public void doLoadAction(Activity context, int action); public void doLoadAction(Activity context, int action);
public abstract boolean onActivityResult(int requestCode, int resultCode, Intent data); public boolean onActivityResult(int requestCode, int resultCode, Intent data);
public SetupDataCallbacks getCallbacks();
} }

View File

@ -120,7 +120,7 @@ public abstract class SetupPage implements Page {
mCallbacks.onPageLoaded(this); mCallbacks.onPageLoaded(this);
} }
protected SetupDataCallbacks getCallbacks() { public SetupDataCallbacks getCallbacks() {
return mCallbacks; return mCallbacks;
} }
} }

View File

@ -18,10 +18,12 @@ package com.cyanogenmod.setupwizard.setup;
import android.app.Fragment; import android.app.Fragment;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.UserHandle;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.NumberPicker; import android.widget.NumberPicker;
@ -35,6 +37,8 @@ public class WelcomePage extends SetupPage {
public static final String TAG = "WelcomePage"; public static final String TAG = "WelcomePage";
private static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
public WelcomePage(Context context, SetupDataCallbacks callbacks) { public WelcomePage(Context context, SetupDataCallbacks callbacks) {
super(context, callbacks); super(context, callbacks);
} }
@ -54,6 +58,15 @@ public class WelcomePage extends SetupPage {
return R.string.setup_welcome; return R.string.setup_welcome;
} }
@Override
public boolean doPreviousAction() {
Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
mContext.startActivity(intent);
return true;
}
@Override @Override
public String getKey() { public String getKey() {
return TAG; return TAG;

View File

@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -32,9 +33,11 @@ import com.cyanogenmod.setupwizard.R;
import com.cyanogenmod.setupwizard.SetupWizardApp; import com.cyanogenmod.setupwizard.SetupWizardApp;
import com.cyanogenmod.setupwizard.setup.AbstractSetupData; import com.cyanogenmod.setupwizard.setup.AbstractSetupData;
import com.cyanogenmod.setupwizard.setup.CMSetupWizardData; import com.cyanogenmod.setupwizard.setup.CMSetupWizardData;
import com.cyanogenmod.setupwizard.setup.CyanogenServicesPage;
import com.cyanogenmod.setupwizard.setup.Page; import com.cyanogenmod.setupwizard.setup.Page;
import com.cyanogenmod.setupwizard.setup.SetupDataCallbacks; import com.cyanogenmod.setupwizard.setup.SetupDataCallbacks;
import com.cyanogenmod.setupwizard.util.SetupWizardUtils; import com.cyanogenmod.setupwizard.util.SetupWizardUtils;
import com.cyanogenmod.setupwizard.util.WhisperPushUtils;
public class SetupWizardActivity extends Activity implements SetupDataCallbacks { public class SetupWizardActivity extends Activity implements SetupDataCallbacks {
@ -209,7 +212,35 @@ public class SetupWizardActivity extends Activity implements SetupDataCallbacks
finishSetup(); finishSetup();
} }
private void handleWhisperPushRegistration() {
Page page = getPage(CyanogenServicesPage.TAG);
if (page == null) {
return;
}
Bundle privacyData = page.getData();
if (privacyData != null && privacyData.getBoolean(CyanogenServicesPage.KEY_REGISTER_WHISPERPUSH)) {
Log.d(TAG, "Registering with WhisperPush");
WhisperPushUtils.startRegistration(this);
}
}
public void handleEnableMetrics() {
Page page = getPage(CyanogenServicesPage.TAG);
if (page == null) {
return;
}
Bundle privacyData = page.getData();
if (privacyData != null
&& privacyData.getBoolean(CyanogenServicesPage.KEY_SEND_METRICS)) {
Settings.System.putInt(getContentResolver(), CyanogenServicesPage.SETTING_METRICS,
privacyData.getBoolean(CyanogenServicesPage.KEY_SEND_METRICS) ? 1 : 0);
}
}
private void finishSetup() { private void finishSetup() {
getApplication().sendBroadcast(new Intent(SetupWizardApp.ACTION_FINISHED));
handleWhisperPushRegistration();
handleEnableMetrics();
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1); Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
((SetupWizardApp)AppGlobals.getInitialApplication()).enableStatusBar(); ((SetupWizardApp)AppGlobals.getInitialApplication()).enableStatusBar();

View File

@ -16,6 +16,7 @@
package com.cyanogenmod.setupwizard.util; package com.cyanogenmod.setupwizard.util;
import android.accounts.AccountManager;
import android.app.Activity; import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@ -138,6 +139,10 @@ public class SetupWizardUtils {
ConnectionResult.SERVICE_MISSING; ConnectionResult.SERVICE_MISSING;
} }
public static boolean accountExists(Context context, String accountType) {
return AccountManager.get(context).getAccountsByType(accountType).length > 0;
}
public static void disableSetupWizards(Activity context) { public static void disableSetupWizards(Activity context) {
Intent intent = new Intent(Intent.ACTION_MAIN); Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME); intent.addCategory(Intent.CATEGORY_HOME);

View File

@ -0,0 +1,78 @@
/*
* 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.util;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
/**
* Utilities for interacting with WhisperPush
*
* @author Chris Soyars
*/
public class WhisperPushUtils {
private static final String TAG = WhisperPushUtils.class.getSimpleName();
private static final String ACTION_REGISTER_NUMBER = "org.thoughtcrime.securesms.RegistrationService.REGISTER_NUMBER";
private static boolean isEmpty(String value) {
return value == null || value.trim().length() == 0;
}
private static String getPhoneNumber(Context context) {
String localNumber = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE))
.getLine1Number();
if (!isEmpty(localNumber) && !localNumber.startsWith("+")) {
if (localNumber.length() == 10) {
localNumber = "+1" + localNumber;
} else {
localNumber = "+" + localNumber;
}
}
try {
if (!isEmpty(localNumber)) {
PhoneNumberUtil numberUtil = PhoneNumberUtil.getInstance();
Phonenumber.PhoneNumber localNumberObject = numberUtil.parse(localNumber, null);
return numberUtil.format(localNumberObject, PhoneNumberUtil.PhoneNumberFormat.E164);
}
} catch (NumberParseException npe) {
Log.w(TAG, npe);
}
return null;
}
public static void startRegistration(Context context) {
String phoneNumber = getPhoneNumber(context);
Log.d(TAG, "Starting WhisperPush registration with number: " + phoneNumber);
if (phoneNumber != null) {
Intent intent = new Intent();
intent.setAction(ACTION_REGISTER_NUMBER);
intent.setClassName("org.whispersystems.whisperpush", "org.whispersystems.whisperpush.service.RegistrationService");
intent.putExtra("e164number", phoneNumber);
context.startService(intent);
}
}
}

View File

@ -9,9 +9,9 @@ LOCAL_JAVA_LIBRARIES := android.test.runner
# Include all test java files. # Include all test java files.
LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CMSetupWizardTests LOCAL_PACKAGE_NAME := CyanogenSetupWizardTests
LOCAL_CERTIFICATE := platform LOCAL_CERTIFICATE := platform
LOCAL_INSTRUMENTATION_FOR := CMSetupWizard LOCAL_INSTRUMENTATION_FOR := CyanogenSetupWizard
include $(BUILD_PACKAGE) include $(BUILD_PACKAGE)

View File

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<resources> <resources>
<string name="app_test">CMSetupWizard Test</string> <string name="app_test">SetupWizard Test</string>
<string name="enable_setup">Enable Setup Wizard</string> <string name="enable_setup">Enable Setup Wizard</string>
<string name="enable_google_setup">Enable Google Setup Wizard</string> <string name="enable_google_setup">Enable Google Setup Wizard</string>
</resources> </resources>

View File

@ -51,7 +51,7 @@ public class ManualTestActivity extends Activity {
Intent intent = new Intent("android.intent.action.MAIN"); Intent intent = new Intent("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME"); intent.addCategory("android.intent.category.HOME");
final PackageManager pm = getPackageManager(); final PackageManager pm = getPackageManager();
ComponentName componentName = new ComponentName("com.cyanogenmod.account", "com.cyanogenmod.account.ui.SetupWizardActivity"); ComponentName componentName = new ComponentName("com.cyanogenmod.setupwizard", "com.cyanogenmod.setupwizard.ui.SetupWizardActivity");
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
componentName = new ComponentName("com.google.android.setupwizard", "com.google.android.setupwizard.SetupWizardActivity"); componentName = new ComponentName("com.google.android.setupwizard", "com.google.android.setupwizard.SetupWizardActivity");
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);