Merge "ResearchLog splash screen"
This commit is contained in:
commit
74c95d6d18
4 changed files with 194 additions and 7 deletions
88
java/res/layout/research_splash.xml
Normal file
88
java/res/layout/research_splash.xml
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2012 The Android Open Source 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:id="@+id/research_splash_screen_layout">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<com.android.internal.widget.DialogTitle
|
||||||
|
style="?android:attr/windowTitleStyle"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dip"
|
||||||
|
android:layout_marginLeft="16dip"
|
||||||
|
android:layout_marginRight="16dip"
|
||||||
|
android:gravity="center_vertical|left"
|
||||||
|
android:text="@string/research_splash_title" />
|
||||||
|
<View android:layout_width="match_parent"
|
||||||
|
android:layout_height="2dip"
|
||||||
|
android:background="@android:color/holo_blue_light" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:text="@string/research_splash_content"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_gravity="fill_horizontal|center_vertical"
|
||||||
|
android:layout_marginLeft="16dip"
|
||||||
|
android:layout_marginRight="16dip"
|
||||||
|
android:layout_marginBottom="16dip"
|
||||||
|
android:layout_marginTop="16dip"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:divider="?android:attr/dividerHorizontal"
|
||||||
|
android:showDividers="beginning"
|
||||||
|
android:dividerPadding="0dip">
|
||||||
|
<LinearLayout
|
||||||
|
style="?android:attr/buttonBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:measureWithLargestChild="true">
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:maxLines="2"
|
||||||
|
stype="?android:attr/buttonBarButtonStyle"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:text="@string/research_dont_send_usage_info"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/research_do_not_log_button" />
|
||||||
|
<Button
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:maxLines="2"
|
||||||
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:text="@string/research_send_usage_info"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/research_do_log_button" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
|
@ -263,6 +263,19 @@
|
||||||
<!-- TODO: remove translatable=false attribute once text is stable -->
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
<string name="research_please_exit_feedback_form" translatable="false">Please exit the feedback dialog to access the research log menu</string>
|
<string name="research_please_exit_feedback_form" translatable="false">Please exit the feedback dialog to access the research log menu</string>
|
||||||
|
|
||||||
|
<!-- Title of dialog shown at start informing users about contributing research usage data-->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_splash_title" translatable="false">Usage Participation</string>
|
||||||
|
<!-- Contents of note explaining what data is collected and how. -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_splash_content" translatable="false">Thank you for dogfooding this keyboard.\n\nIf you like it, please help us make it better by sending us usage information. When enabled, the keyboard uploads general statistics, such as how fast you type, and also occasional samples of how you type words.\n\nNo passwords or non-dictionary words are ever automatically uploaded, and words are sampled infrequently enough so that reconstructing the meaning of what you typed is highly unlikely.\n\nYou can disable and reenable logging through the RLog menu by long-pressing on the microphone or settings key.\n</string>
|
||||||
|
<!-- Button label text for opting out of research usage data collection [CHAR LIMIT=50] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_dont_send_usage_info" translatable="false">Do not send\nusage info</string>
|
||||||
|
<!-- Button label text for opting into research usage data collection [CHAR LIMIT=50] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_send_usage_info" translatable="false">Send usage info</string>
|
||||||
|
|
||||||
<!-- Preference for input language selection -->
|
<!-- Preference for input language selection -->
|
||||||
<string name="select_language">Input languages</string>
|
<string name="select_language">Input languages</string>
|
||||||
|
|
||||||
|
|
|
@ -508,6 +508,17 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
|
||||||
return mKeyDetector.isProximityCorrectionEnabled();
|
return mKeyDetector.isProximityCorrectionEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAttachedToWindow() {
|
||||||
|
super.onAttachedToWindow();
|
||||||
|
// Notify the research logger that the keyboard view has been attached. This is needed
|
||||||
|
// to properly show the splash screen, which requires that the window token of the
|
||||||
|
// KeyboardView be non-null.
|
||||||
|
if (ProductionFlag.IS_EXPERIMENTAL) {
|
||||||
|
ResearchLogger.getInstance().latinKeyboardView_onAttachedToWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancelAllMessages() {
|
public void cancelAllMessages() {
|
||||||
mKeyTimerHandler.cancelAllMessages();
|
mKeyTimerHandler.cancelAllMessages();
|
||||||
|
|
|
@ -19,27 +19,36 @@ package com.android.inputmethod.research;
|
||||||
import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
|
import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOARD_LAYOUT_SET;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.DialogInterface.OnCancelListener;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.Editor;
|
import android.content.SharedPreferences.Editor;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.inputmethodservice.InputMethodService;
|
import android.inputmethodservice.InputMethodService;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.format.DateUtils;
|
import android.text.format.DateUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.view.inputmethod.CompletionInfo;
|
import android.view.inputmethod.CompletionInfo;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.inputmethod.keyboard.Key;
|
import com.android.inputmethod.keyboard.Key;
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
import com.android.inputmethod.keyboard.KeyboardId;
|
import com.android.inputmethod.keyboard.KeyboardId;
|
||||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||||
|
import com.android.inputmethod.keyboard.LatinKeyboardView;
|
||||||
import com.android.inputmethod.latin.Dictionary;
|
import com.android.inputmethod.latin.Dictionary;
|
||||||
import com.android.inputmethod.latin.LatinIME;
|
import com.android.inputmethod.latin.LatinIME;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
|
@ -73,6 +82,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
/* package */ static boolean sIsLogging = false;
|
/* package */ static boolean sIsLogging = false;
|
||||||
private static final int OUTPUT_FORMAT_VERSION = 1;
|
private static final int OUTPUT_FORMAT_VERSION = 1;
|
||||||
private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
|
private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
|
||||||
|
private static final String PREF_RESEARCH_HAS_SEEN_SPLASH = "pref_research_has_seen_splash";
|
||||||
/* package */ static final String FILENAME_PREFIX = "researchLog";
|
/* package */ static final String FILENAME_PREFIX = "researchLog";
|
||||||
private static final String FILENAME_SUFFIX = ".txt";
|
private static final String FILENAME_SUFFIX = ".txt";
|
||||||
private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
|
private static final SimpleDateFormat TIMESTAMP_DATEFORMAT =
|
||||||
|
@ -118,7 +128,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
private Suggest mSuggest;
|
private Suggest mSuggest;
|
||||||
private Dictionary mDictionary;
|
private Dictionary mDictionary;
|
||||||
private KeyboardSwitcher mKeyboardSwitcher;
|
private KeyboardSwitcher mKeyboardSwitcher;
|
||||||
private Context mContext;
|
private InputMethodService mInputMethodService;
|
||||||
|
|
||||||
private ResearchLogUploader mResearchLogUploader;
|
private ResearchLogUploader mResearchLogUploader;
|
||||||
|
|
||||||
|
@ -163,11 +173,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
mResearchLogUploader = new ResearchLogUploader(ims, mFilesDir);
|
mResearchLogUploader = new ResearchLogUploader(ims, mFilesDir);
|
||||||
mResearchLogUploader.start();
|
mResearchLogUploader.start();
|
||||||
mKeyboardSwitcher = keyboardSwitcher;
|
mKeyboardSwitcher = keyboardSwitcher;
|
||||||
mContext = ims;
|
mInputMethodService = ims;
|
||||||
mPrefs = prefs;
|
mPrefs = prefs;
|
||||||
|
|
||||||
// TODO: force user to decide at splash screen instead of defaulting to on.
|
|
||||||
setLoggingAllowed(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cleanupLoggingDir(final File dir, final long time) {
|
private void cleanupLoggingDir(final File dir, final long time) {
|
||||||
|
@ -179,6 +186,73 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void latinKeyboardView_onAttachedToWindow() {
|
||||||
|
maybeShowSplashScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasSeenSplash() {
|
||||||
|
return mPrefs.getBoolean(PREF_RESEARCH_HAS_SEEN_SPLASH, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dialog mSplashDialog = null;
|
||||||
|
|
||||||
|
private void maybeShowSplashScreen() {
|
||||||
|
if (hasSeenSplash()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mSplashDialog != null && mSplashDialog.isShowing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final IBinder windowToken = mKeyboardSwitcher.getKeyboardView().getWindowToken();
|
||||||
|
if (windowToken == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mSplashDialog = new Dialog(mInputMethodService, android.R.style.Theme_Holo_Dialog);
|
||||||
|
mSplashDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
mSplashDialog.setContentView(R.layout.research_splash);
|
||||||
|
mSplashDialog.setCancelable(true);
|
||||||
|
final Window w = mSplashDialog.getWindow();
|
||||||
|
final WindowManager.LayoutParams lp = w.getAttributes();
|
||||||
|
lp.token = windowToken;
|
||||||
|
lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
|
||||||
|
w.setAttributes(lp);
|
||||||
|
w.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||||
|
mSplashDialog.setOnCancelListener(new OnCancelListener() {
|
||||||
|
@Override
|
||||||
|
public void onCancel(DialogInterface dialog) {
|
||||||
|
mInputMethodService.requestHideSelf(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
final Button doNotLogButton = (Button) mSplashDialog.findViewById(
|
||||||
|
R.id.research_do_not_log_button);
|
||||||
|
doNotLogButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
onUserLoggingElection(false);
|
||||||
|
mSplashDialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
final Button doLogButton = (Button) mSplashDialog.findViewById(R.id.research_do_log_button);
|
||||||
|
doLogButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
onUserLoggingElection(true);
|
||||||
|
mSplashDialog.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mSplashDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUserLoggingElection(final boolean enableLogging) {
|
||||||
|
setLoggingAllowed(enableLogging);
|
||||||
|
if (mPrefs == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Editor e = mPrefs.edit();
|
||||||
|
e.putBoolean(PREF_RESEARCH_HAS_SEEN_SPLASH, true);
|
||||||
|
e.apply();
|
||||||
|
}
|
||||||
|
|
||||||
private File createLogFile(File filesDir) {
|
private File createLogFile(File filesDir) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
sb.append(FILENAME_PREFIX).append('-');
|
sb.append(FILENAME_PREFIX).append('-');
|
||||||
|
@ -189,6 +263,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start() {
|
private void start() {
|
||||||
|
maybeShowSplashScreen();
|
||||||
updateSuspendedState();
|
updateSuspendedState();
|
||||||
requestIndicatorRedraw();
|
requestIndicatorRedraw();
|
||||||
if (!isAllowedToLog()) {
|
if (!isAllowedToLog()) {
|
||||||
|
@ -705,7 +780,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
researchLogger.start();
|
researchLogger.start();
|
||||||
if (editorInfo != null) {
|
if (editorInfo != null) {
|
||||||
final Context context = researchLogger.mContext;
|
final Context context = researchLogger.mInputMethodService;
|
||||||
try {
|
try {
|
||||||
final PackageInfo packageInfo;
|
final PackageInfo packageInfo;
|
||||||
packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
|
packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(),
|
||||||
|
@ -900,7 +975,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
// Play it safe. Remove privacy-sensitive events.
|
// Play it safe. Remove privacy-sensitive events.
|
||||||
researchLogger.publishLogUnit(researchLogger.mCurrentLogUnit, true);
|
researchLogger.publishLogUnit(researchLogger.mCurrentLogUnit, true);
|
||||||
researchLogger.mCurrentLogUnit = new LogUnit();
|
researchLogger.mCurrentLogUnit = new LogUnit();
|
||||||
getInstance().restart();
|
getInstance().stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue