Merge "Move splash screen to separate file"

This commit is contained in:
Kurt Partridge 2013-06-24 13:40:00 +00:00 committed by Android (Google) Code Review
commit 1fc6b80009
2 changed files with 125 additions and 62 deletions

View File

@ -20,11 +20,7 @@ import static com.android.inputmethod.latin.Constants.Subtype.ExtraValue.KEYBOAR
import android.accounts.Account; import android.accounts.Account;
import android.accounts.AccountManager; import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
@ -34,7 +30,6 @@ import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -46,8 +41,6 @@ import android.text.format.DateUtils;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
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;
@ -70,6 +63,7 @@ import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.define.ProductionFlag; import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.utils.InputTypeUtils; import com.android.inputmethod.latin.utils.InputTypeUtils;
import com.android.inputmethod.research.MotionEventReader.ReplayData; import com.android.inputmethod.research.MotionEventReader.ReplayData;
import com.android.inputmethod.research.ui.SplashScreen;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -94,12 +88,12 @@ import java.util.regex.Pattern;
* This functionality is off by default. See * This functionality is off by default. See
* {@link ProductionFlag#USES_DEVELOPMENT_ONLY_DIAGNOSTICS}. * {@link ProductionFlag#USES_DEVELOPMENT_ONLY_DIAGNOSTICS}.
*/ */
public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener,
SplashScreen.UserConsentListener {
// TODO: This class has grown quite large and combines several concerns that should be // TODO: This class has grown quite large and combines several concerns that should be
// separated. The following refactorings will be applied as soon as possible after adding // separated. The following refactorings will be applied as soon as possible after adding
// support for replaying historical events, fixing some replay bugs, adding some ui constraints // support for replaying historical events, fixing some replay bugs, adding some ui constraints
// on the feedback dialog, and adding the survey dialog. // on the feedback dialog, and adding the survey dialog.
// TODO: Refactor. Move splash screen code into separate class.
// TODO: Refactor. Move feedback screen code into separate class. // TODO: Refactor. Move feedback screen code into separate class.
// TODO: Refactor. Move logging invocations into their own class. // TODO: Refactor. Move logging invocations into their own class.
// TODO: Refactor. Move currentLogUnit management into separate class. // TODO: Refactor. Move currentLogUnit management into separate class.
@ -184,6 +178,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private final MotionEventReader mMotionEventReader = new MotionEventReader(); private final MotionEventReader mMotionEventReader = new MotionEventReader();
private final Replayer mReplayer = Replayer.getInstance(); private final Replayer mReplayer = Replayer.getInstance();
private ResearchLogDirectory mResearchLogDirectory; private ResearchLogDirectory mResearchLogDirectory;
private SplashScreen mSplashScreen;
private Intent mUploadIntent; private Intent mUploadIntent;
private Intent mUploadNowIntent; private Intent mUploadNowIntent;
@ -301,62 +296,19 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
} }
} }
private Dialog mSplashDialog = null;
private void maybeShowSplashScreen() { private void maybeShowSplashScreen() {
if (ResearchSettings.readHasSeenSplash(mPrefs)) { if (ResearchSettings.readHasSeenSplash(mPrefs)) return;
return; if (mSplashScreen != null && mSplashScreen.isShowing()) return;
} if (mMainKeyboardView == null) return;
if (mSplashDialog != null && mSplashDialog.isShowing()) { final IBinder windowToken = mMainKeyboardView.getWindowToken();
return; if (windowToken == null) return;
}
final IBinder windowToken = mMainKeyboardView != null mSplashScreen = new SplashScreen(mLatinIME, this);
? mMainKeyboardView.getWindowToken() : null; mSplashScreen.showSplashScreen(windowToken);
if (windowToken == null) {
return;
}
final AlertDialog.Builder builder = new AlertDialog.Builder(mLatinIME)
.setTitle(R.string.research_splash_title)
.setMessage(R.string.research_splash_content)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
onUserLoggingConsent();
mSplashDialog.dismiss();
}
})
.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final String packageName = mLatinIME.getPackageName();
final Uri packageUri = Uri.parse("package:" + packageName);
final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE,
packageUri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mLatinIME.startActivity(intent);
}
})
.setCancelable(true)
.setOnCancelListener(
new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
mLatinIME.requestHideSelf(0);
}
});
mSplashDialog = builder.create();
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.show();
} }
public void onUserLoggingConsent() { @Override
public void onSplashScreenUserClickedOk() {
if (mPrefs == null) { if (mPrefs == null) {
mPrefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME); mPrefs = PreferenceManager.getDefaultSharedPreferences(mLatinIME);
if (mPrefs == null) return; if (mPrefs == null) return;

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2013 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.
*/
package com.android.inputmethod.research.ui;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.IBinder;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import com.android.inputmethod.latin.R.string;
/**
* Show a dialog when the user first opens the keyboard.
*
* The splash screen is a modal dialog box presented when the user opens this keyboard for the first
* time. It is useful for giving specific warnings that must be shown to the user before use.
*
* While the splash screen does share with the setup wizard the common goal of presenting
* information to the user before use, they are presented at different times and with different
* capabilities. The setup wizard is launched by tapping on the icon, and walks the user through
* the setup process. It can, however, be bypassed by enabling the keyboard from Settings directly.
* The splash screen cannot be bypassed, and is therefore more appropriate for obtaining user
* consent.
*/
public class SplashScreen {
public interface UserConsentListener {
public void onSplashScreenUserClickedOk();
}
final UserConsentListener mListener;
final Dialog mSplashDialog;
public SplashScreen(final InputMethodService inputMethodService,
final UserConsentListener listener) {
mListener = listener;
final Builder builder = new Builder(inputMethodService)
.setTitle(string.research_splash_title)
.setMessage(string.research_splash_content)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mListener.onSplashScreenUserClickedOk();
mSplashDialog.dismiss();
}
})
.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final String packageName = inputMethodService.getPackageName();
final Uri packageUri = Uri.parse("package:" + packageName);
final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE,
packageUri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
inputMethodService.startActivity(intent);
}
})
.setCancelable(true)
.setOnCancelListener(
new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
inputMethodService.requestHideSelf(0);
}
});
mSplashDialog = builder.create();
}
/**
* Show the splash screen.
*
* The user must consent to the terms presented in the SplashScreen before they can use the
* keyboard. If they cancel instead, they are given the option to uninstall the keybard.
*
* @param windowToken {@link IBinder} to attach dialog to
*/
public void showSplashScreen(final IBinder windowToken) {
final Window window = mSplashDialog.getWindow();
final LayoutParams lp = window.getAttributes();
lp.token = windowToken;
lp.type = LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
window.setAttributes(lp);
window.addFlags(LayoutParams.FLAG_ALT_FOCUSABLE_IM);
mSplashDialog.show();
}
public boolean isShowing() {
return mSplashDialog.isShowing();
}
}