Merge "ResearchLogger feedback form"
This commit is contained in:
commit
f0c6606807
9 changed files with 539 additions and 63 deletions
31
java/res/layout/research_feedback_activity.xml
Normal file
31
java/res/layout/research_feedback_activity.xml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<com.android.inputmethod.research.FeedbackLayout
|
||||||
|
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_feedback_layout"
|
||||||
|
>
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/research_feedback_fragment"
|
||||||
|
android:name="com.android.inputmethod.research.FeedbackFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
</com.android.inputmethod.research.FeedbackLayout>
|
112
java/res/layout/research_feedback_fragment_layout.xml
Normal file
112
java/res/layout/research_feedback_fragment_layout.xml
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<?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="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- Mimic a dialog title. Necessary since the dialog is actually an activity, so the normal
|
||||||
|
dialog title construction code is not available. -->
|
||||||
|
<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_feedback_dialog_title" />
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="2dip"
|
||||||
|
android:background="@android:color/holo_blue_light" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/research_feedback_contents"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_gravity="fill_horizontal|center_vertical"
|
||||||
|
android:layout_marginLeft="8dip"
|
||||||
|
android:layout_marginRight="8dip"
|
||||||
|
android:layout_marginBottom="8dip"
|
||||||
|
android:layout_marginTop="8dip"
|
||||||
|
android:lines="2"
|
||||||
|
android:hint="@string/research_feedback_hint"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:imeOptions="flagNoFullscreen"
|
||||||
|
>
|
||||||
|
<requestFocus />
|
||||||
|
</EditText>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/research_feedback_include_history"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginBottom="8dip"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/research_feedback_include_history_label"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<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:id="@+id/research_feedback_cancel_button"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:maxLines="2"
|
||||||
|
style="?android:attr/buttonBarButtonStyle"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:text="@string/research_feedback_cancel"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/research_feedback_send_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_feedback_send"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
50
java/res/layout/research_feedback_layout.xml
Normal file
50
java/res/layout/research_feedback_layout.xml
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<?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="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/research_feedback_contents"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_gravity="fill_horizontal|center_vertical"
|
||||||
|
android:layout_marginLeft="8dip"
|
||||||
|
android:layout_marginRight="8dip"
|
||||||
|
android:layout_marginBottom="8dip"
|
||||||
|
android:layout_marginTop="8dip"
|
||||||
|
android:lines="2"
|
||||||
|
android:hint="@string/research_feedback_hint"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:imeOptions="flagNoFullscreen"
|
||||||
|
android:focusable="true"
|
||||||
|
>
|
||||||
|
<requestFocus />
|
||||||
|
</EditText>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/research_feedback_include_history"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginBottom="8dip"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/research_feedback_include_history_label"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
|
@ -222,29 +222,47 @@
|
||||||
<!-- Title for input language selection screen -->
|
<!-- Title for input language selection screen -->
|
||||||
<string name="language_selection_title">Input languages</string>
|
<string name="language_selection_title">Input languages</string>
|
||||||
|
|
||||||
<!-- Title for dialog option that lets user mark a particular time in the log for later review by experts [CHAR LIMIT=38] -->
|
|
||||||
<string name="note_timestamp_for_researchlog">Note timestamp in log</string>
|
|
||||||
<!-- Toast notification message that the time has been marked for later review. [CHAR LIMIT=25] -->
|
|
||||||
<string name="notify_recorded_timestamp">Recorded timestamp</string>
|
|
||||||
|
|
||||||
<!-- Title for dialog option to let users cancel logging and delete log for this session [CHAR LIMIT=35] -->
|
<!-- Title for dialog option to let users cancel logging and delete log for this session [CHAR LIMIT=35] -->
|
||||||
<string name="do_not_log_this_session">Suspend logging</string>
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_do_not_log_this_session" translatable="false">Suspend logging</string>
|
||||||
<!-- Title for dialog option to let users reenable logging [CHAR LIMIT=35] -->
|
<!-- Title for dialog option to let users reenable logging [CHAR LIMIT=35] -->
|
||||||
<string name="enable_session_logging">Enable logging</string>
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
<!-- Title for dialog option to let users log all events in this session [CHAR LIMIT=35] -->
|
<string name="research_enable_session_logging" translatable="false">Enable logging</string>
|
||||||
<string name="log_whole_session_history">Log whole session history</string>
|
|
||||||
<!-- Toast notification that the system is processing the request to delete the log for this session [CHAR LIMIT=35] -->
|
<!-- Toast notification that the system is processing the request to delete the log for this session [CHAR LIMIT=35] -->
|
||||||
<string name="notify_session_log_deleting">Deleting session log</string>
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_notify_session_log_deleting" translatable="false">Deleting session log</string>
|
||||||
<!-- Toast notification that the system has successfully deleted the log for this session [CHAR LIMIT=35] -->
|
<!-- Toast notification that the system has successfully deleted the log for this session [CHAR LIMIT=35] -->
|
||||||
<string name="notify_logging_suspended">Logging temporarily suspended. To disable permanently, go to Android Keyboard Settings</string>
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_notify_logging_suspended" translatable="false">Logging temporarily suspended. To disable permanently, go to Android Keyboard Settings</string>
|
||||||
<!-- Toast notification that the system has failed to delete the log for this session [CHAR LIMIT=35] -->
|
<!-- Toast notification that the system has failed to delete the log for this session [CHAR LIMIT=35] -->
|
||||||
<string name="notify_session_log_not_deleted">Session log NOT deleted</string>
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
<!-- Toast notification that the system has recorded the whole session history [CHAR LIMIT=35] -->
|
<string name="research_notify_session_log_not_deleted" translatable="false">Session log NOT deleted</string>
|
||||||
<string name="notify_session_history_logged">Session history logged</string>
|
|
||||||
<!-- Toast notification that the system has failed to record the whole session history [CHAR LIMIT=35] -->
|
|
||||||
<string name="notify_session_history_not_logged">Error: Session history NOT logged</string>
|
|
||||||
<!-- Toast notification that the system is enabling logging [CHAR LIMIT=35] -->
|
<!-- Toast notification that the system is enabling logging [CHAR LIMIT=35] -->
|
||||||
<string name="notify_session_logging_enabled">Session logging enabled</string>
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_notify_session_logging_enabled" translatable="false">Session logging enabled</string>
|
||||||
|
|
||||||
|
<!-- Menu option that lets user send feedback for research purposes about the IME [CHAR LIMIT=38] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_feedback_menu_option" translatable="false">Send feedback</string>
|
||||||
|
<!-- Dialog box title that lets user send feedback for research purposes about the IME [CHAR LIMIT=38] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_feedback_dialog_title" translatable="false">Send feedback</string>
|
||||||
|
<!-- Text for checkbox option to include user data in feedback for research purposes [CHAR LIMIT=50] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_feedback_include_history_label" translatable="false">Include last 5 words entered</string>
|
||||||
|
<!-- Hint to user about the text entry field where they should enter research feedback [CHAR LIMIT=40] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_feedback_hint" translatable="false">Enter your feedback here.</string>
|
||||||
|
<!-- Dialog button choice to send research feedback [CHAR LIMIT=35] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_feedback_send" translatable="false">Send</string>
|
||||||
|
<!-- Dialog button choice to cancel sending research feedback [CHAR LIMIT=35] -->
|
||||||
|
<!-- TODO: remove translatable=false attribute once text is stable -->
|
||||||
|
<string name="research_feedback_cancel" translatable="false">Cancel</string>
|
||||||
|
<!-- Toast notification to ask user to quit the research feedback dialog to perform this operation [CHAR LIMIT=100] -->
|
||||||
|
<!-- 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>
|
||||||
|
|
||||||
<!-- Preference for input language selection -->
|
<!-- Preference for input language selection -->
|
||||||
<string name="select_language">Input languages</string>
|
<string name="select_language">Input languages</string>
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
|
||||||
import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
|
import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
|
||||||
import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -38,7 +39,6 @@ import android.os.Debug;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.preference.PreferenceActivity;
|
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -2111,18 +2111,26 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
};
|
};
|
||||||
|
|
||||||
private void launchSettings() {
|
private void launchSettings() {
|
||||||
launchSettingsClass(SettingsActivity.class);
|
handleClose();
|
||||||
|
launchSubActivity(SettingsActivity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from debug code only
|
// Called from debug code only
|
||||||
public void launchDebugSettings() {
|
public void launchDebugSettings() {
|
||||||
launchSettingsClass(DebugSettingsActivity.class);
|
handleClose();
|
||||||
|
launchSubActivity(DebugSettingsActivity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) {
|
public void launchKeyboardedDialogActivity(Class<? extends Activity> activityClass) {
|
||||||
handleClose();
|
// Put the text in the attached EditText into a safe, saved state before switching to a
|
||||||
|
// new activity that will also use the soft keyboard.
|
||||||
|
commitTyped(LastComposedWord.NOT_A_SEPARATOR);
|
||||||
|
launchSubActivity(activityClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void launchSubActivity(Class<? extends Activity> activityClass) {
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent();
|
||||||
intent.setClass(LatinIME.this, settingsClass);
|
intent.setClass(LatinIME.this, activityClass);
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.research;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
public class FeedbackActivity extends Activity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.research_feedback_activity);
|
||||||
|
final FeedbackLayout layout = (FeedbackLayout) findViewById(R.id.research_feedback_layout);
|
||||||
|
layout.setActivity(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
ResearchLogger.getInstance().onLeavingSendFeedbackDialog();
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.research;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
|
||||||
|
public class FeedbackFragment extends Fragment {
|
||||||
|
private EditText mEditText;
|
||||||
|
private CheckBox mCheckBox;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
final View view = inflater.inflate(R.layout.research_feedback_fragment_layout, container,
|
||||||
|
false);
|
||||||
|
mEditText = (EditText) view.findViewById(R.id.research_feedback_contents);
|
||||||
|
mCheckBox = (CheckBox) view.findViewById(R.id.research_feedback_include_history);
|
||||||
|
|
||||||
|
final Button sendButton = (Button) view.findViewById(
|
||||||
|
R.id.research_feedback_send_button);
|
||||||
|
sendButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final Editable editable = mEditText.getText();
|
||||||
|
final String feedbackContents = editable.toString();
|
||||||
|
final boolean includeHistory = mCheckBox.isChecked();
|
||||||
|
ResearchLogger.getInstance().sendFeedback(feedbackContents, includeHistory);
|
||||||
|
final Activity activity = FeedbackFragment.this.getActivity();
|
||||||
|
activity.finish();
|
||||||
|
ResearchLogger.getInstance().onLeavingSendFeedbackDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final Button cancelButton = (Button) view.findViewById(
|
||||||
|
R.id.research_feedback_cancel_button);
|
||||||
|
cancelButton.setOnClickListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final Activity activity = FeedbackFragment.this.getActivity();
|
||||||
|
activity.finish();
|
||||||
|
ResearchLogger.getInstance().onLeavingSendFeedbackDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.inputmethod.research;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
public class FeedbackLayout extends LinearLayout {
|
||||||
|
private Activity mActivity;
|
||||||
|
|
||||||
|
public FeedbackLayout(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedbackLayout(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedbackLayout(Context context, AttributeSet attrs, int defstyle) {
|
||||||
|
super(context, attrs, defstyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActivity(Activity activity) {
|
||||||
|
mActivity = activity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean dispatchKeyEventPreIme(KeyEvent event) {
|
||||||
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||||
|
KeyEvent.DispatcherState state = getKeyDispatcherState();
|
||||||
|
if (state != null) {
|
||||||
|
if (event.getAction() == KeyEvent.ACTION_DOWN
|
||||||
|
&& event.getRepeatCount() == 0) {
|
||||||
|
state.startTracking(event, this);
|
||||||
|
return true;
|
||||||
|
} else if (event.getAction() == KeyEvent.ACTION_UP
|
||||||
|
&& !event.isCanceled() && state.isTracking(event)) {
|
||||||
|
mActivity.onBackPressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.dispatchKeyEventPreIme(event);
|
||||||
|
}
|
||||||
|
}
|
|
@ -83,7 +83,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
private static final String WHITESPACE_SEPARATORS = " \t\n\r";
|
private static final String WHITESPACE_SEPARATORS = " \t\n\r";
|
||||||
private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
|
private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
|
||||||
private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid";
|
private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid";
|
||||||
private static final int ABORT_TIMEOUT_IN_MS = 10 * 1000;
|
private static final int ABORT_TIMEOUT_IN_MS = 10 * 1000; // timeout to notify user
|
||||||
|
|
||||||
private static final ResearchLogger sInstance = new ResearchLogger();
|
private static final ResearchLogger sInstance = new ResearchLogger();
|
||||||
// to write to a different filename, e.g., for testing, set mFile before calling start()
|
// to write to a different filename, e.g., for testing, set mFile before calling start()
|
||||||
|
@ -95,7 +95,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
// the system to do so.
|
// the system to do so.
|
||||||
/* package */ ResearchLog mIntentionalResearchLog;
|
/* package */ ResearchLog mIntentionalResearchLog;
|
||||||
// LogUnits are queued here and released only when the user requests the intentional log.
|
// LogUnits are queued here and released only when the user requests the intentional log.
|
||||||
private final List<LogUnit> mIntentionalResearchLogQueue = new ArrayList<LogUnit>();
|
private List<LogUnit> mIntentionalResearchLogQueue = new ArrayList<LogUnit>();
|
||||||
|
|
||||||
private boolean mIsPasswordView = false;
|
private boolean mIsPasswordView = false;
|
||||||
private boolean mIsLoggingSuspended = false;
|
private boolean mIsLoggingSuspended = false;
|
||||||
|
@ -268,22 +268,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logWholeSessionHistory() throws IOException {
|
|
||||||
try {
|
|
||||||
LogUnit headerLogUnit = new LogUnit();
|
|
||||||
headerLogUnit.addLogAtom(EVENTKEYS_INTENTIONAL_LOG, EVENTKEYS_NULLVALUES, false);
|
|
||||||
mIntentionalResearchLog.publishAllEvents(headerLogUnit);
|
|
||||||
for (LogUnit logUnit : mIntentionalResearchLogQueue) {
|
|
||||||
mIntentionalResearchLog.publishAllEvents(logUnit);
|
|
||||||
}
|
|
||||||
mIntentionalResearchLog.stop();
|
|
||||||
mIntentionalResearchLog = new ResearchLog(createLogFile(mFilesDir));
|
|
||||||
mIntentionalResearchLog.start();
|
|
||||||
} finally {
|
|
||||||
mIntentionalResearchLogQueue.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void restart() {
|
private void restart() {
|
||||||
stop();
|
stop();
|
||||||
start();
|
start();
|
||||||
|
@ -325,13 +309,17 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public void presentResearchDialog(final LatinIME latinIME) {
|
public void presentResearchDialog(final LatinIME latinIME) {
|
||||||
|
if (mInFeedbackDialog) {
|
||||||
|
Toast.makeText(latinIME, R.string.research_please_exit_feedback_form,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
final CharSequence title = latinIME.getString(R.string.english_ime_research_log);
|
final CharSequence title = latinIME.getString(R.string.english_ime_research_log);
|
||||||
final boolean showEnable = mIsLoggingSuspended || !sIsLogging;
|
final boolean showEnable = mIsLoggingSuspended || !sIsLogging;
|
||||||
final CharSequence[] items = new CharSequence[] {
|
final CharSequence[] items = new CharSequence[] {
|
||||||
latinIME.getString(R.string.note_timestamp_for_researchlog),
|
latinIME.getString(R.string.research_feedback_menu_option),
|
||||||
showEnable ? latinIME.getString(R.string.enable_session_logging) :
|
showEnable ? latinIME.getString(R.string.research_enable_session_logging) :
|
||||||
latinIME.getString(R.string.do_not_log_this_session),
|
latinIME.getString(R.string.research_do_not_log_this_session)
|
||||||
latinIME.getString(R.string.log_whole_session_history)
|
|
||||||
};
|
};
|
||||||
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
|
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -339,9 +327,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
di.dismiss();
|
di.dismiss();
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case 0:
|
case 0:
|
||||||
userTimestamp();
|
presentFeedbackDialog(latinIME);
|
||||||
Toast.makeText(latinIME, R.string.notify_recorded_timestamp,
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (showEnable) {
|
if (showEnable) {
|
||||||
|
@ -349,11 +335,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
setLoggingAllowed(true);
|
setLoggingAllowed(true);
|
||||||
}
|
}
|
||||||
resumeLogging();
|
resumeLogging();
|
||||||
Toast.makeText(latinIME, R.string.notify_session_logging_enabled,
|
Toast.makeText(latinIME,
|
||||||
|
R.string.research_notify_session_logging_enabled,
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
} else {
|
} else {
|
||||||
Toast toast = Toast.makeText(latinIME,
|
Toast toast = Toast.makeText(latinIME,
|
||||||
R.string.notify_session_log_deleting, Toast.LENGTH_LONG);
|
R.string.research_notify_session_log_deleting,
|
||||||
|
Toast.LENGTH_LONG);
|
||||||
toast.show();
|
toast.show();
|
||||||
boolean isLogDeleted = abort();
|
boolean isLogDeleted = abort();
|
||||||
final long currentTime = System.currentTimeMillis();
|
final long currentTime = System.currentTimeMillis();
|
||||||
|
@ -361,21 +349,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
SUSPEND_DURATION_IN_MINUTES;
|
SUSPEND_DURATION_IN_MINUTES;
|
||||||
suspendLoggingUntil(resumeTime);
|
suspendLoggingUntil(resumeTime);
|
||||||
toast.cancel();
|
toast.cancel();
|
||||||
Toast.makeText(latinIME, R.string.notify_logging_suspended,
|
Toast.makeText(latinIME, R.string.research_notify_logging_suspended,
|
||||||
Toast.LENGTH_LONG).show();
|
Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
|
||||||
try {
|
|
||||||
logWholeSessionHistory();
|
|
||||||
Toast.makeText(latinIME, R.string.notify_session_history_logged,
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Toast.makeText(latinIME, R.string.notify_session_history_not_logged,
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,6 +363,83 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
latinIME.showOptionDialog(builder.create());
|
latinIME.showOptionDialog(builder.create());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean mInFeedbackDialog = false;
|
||||||
|
public void presentFeedbackDialog(LatinIME latinIME) {
|
||||||
|
mInFeedbackDialog = true;
|
||||||
|
latinIME.launchKeyboardedDialogActivity(FeedbackActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResearchLog mFeedbackLog;
|
||||||
|
private List<LogUnit> mFeedbackQueue;
|
||||||
|
private ResearchLog mSavedMainResearchLog;
|
||||||
|
private ResearchLog mSavedIntentionalResearchLog;
|
||||||
|
private List<LogUnit> mSavedIntentionalResearchLogQueue;
|
||||||
|
|
||||||
|
private void saveLogsForFeedback() {
|
||||||
|
mFeedbackLog = mIntentionalResearchLog;
|
||||||
|
if (mIntentionalResearchLogQueue != null) {
|
||||||
|
mFeedbackQueue = new ArrayList<LogUnit>(mIntentionalResearchLogQueue);
|
||||||
|
} else {
|
||||||
|
mFeedbackQueue = null;
|
||||||
|
}
|
||||||
|
mSavedMainResearchLog = mMainResearchLog;
|
||||||
|
mSavedIntentionalResearchLog = mIntentionalResearchLog;
|
||||||
|
mSavedIntentionalResearchLogQueue = mIntentionalResearchLogQueue;
|
||||||
|
|
||||||
|
mMainResearchLog = null;
|
||||||
|
mIntentionalResearchLog = null;
|
||||||
|
mIntentionalResearchLogQueue = new ArrayList<LogUnit>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final int LOG_DRAIN_TIMEOUT_IN_MS = 1000 * 5;
|
||||||
|
public void sendFeedback(final String feedbackContents, final boolean includeHistory) {
|
||||||
|
if (includeHistory && mFeedbackLog != null) {
|
||||||
|
try {
|
||||||
|
LogUnit headerLogUnit = new LogUnit();
|
||||||
|
headerLogUnit.addLogAtom(EVENTKEYS_INTENTIONAL_LOG, EVENTKEYS_NULLVALUES, false);
|
||||||
|
mFeedbackLog.publishAllEvents(headerLogUnit);
|
||||||
|
for (LogUnit logUnit : mFeedbackQueue) {
|
||||||
|
mFeedbackLog.publishAllEvents(logUnit);
|
||||||
|
}
|
||||||
|
userFeedback(mFeedbackLog, feedbackContents);
|
||||||
|
mFeedbackLog.stop();
|
||||||
|
try {
|
||||||
|
mFeedbackLog.waitUntilStopped(LOG_DRAIN_TIMEOUT_IN_MS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
mIntentionalResearchLog = new ResearchLog(createLogFile(mFilesDir));
|
||||||
|
mIntentionalResearchLog.start();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
mIntentionalResearchLogQueue.clear();
|
||||||
|
}
|
||||||
|
mResearchLogUploader.uploadNow(null);
|
||||||
|
} else {
|
||||||
|
// create a separate ResearchLog just for feedback
|
||||||
|
final ResearchLog feedbackLog = new ResearchLog(createLogFile(mFilesDir));
|
||||||
|
try {
|
||||||
|
feedbackLog.start();
|
||||||
|
userFeedback(feedbackLog, feedbackContents);
|
||||||
|
feedbackLog.stop();
|
||||||
|
feedbackLog.waitUntilStopped(LOG_DRAIN_TIMEOUT_IN_MS);
|
||||||
|
mResearchLogUploader.uploadNow(null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onLeavingSendFeedbackDialog() {
|
||||||
|
mInFeedbackDialog = false;
|
||||||
|
mMainResearchLog = mSavedMainResearchLog;
|
||||||
|
mIntentionalResearchLog = mSavedIntentionalResearchLog;
|
||||||
|
mIntentionalResearchLogQueue = mSavedIntentionalResearchLogQueue;
|
||||||
|
}
|
||||||
|
|
||||||
public void initSuggest(Suggest suggest) {
|
public void initSuggest(Suggest suggest) {
|
||||||
mSuggest = suggest;
|
mSuggest = suggest;
|
||||||
}
|
}
|
||||||
|
@ -540,7 +594,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mMainResearchLog == null) {
|
if (mMainResearchLog == null) {
|
||||||
Log.w(TAG, "ResearchLog was not properly set up");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isPrivacySensitive) {
|
if (isPrivacySensitive) {
|
||||||
|
@ -647,6 +700,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
|
public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo,
|
||||||
final SharedPreferences prefs) {
|
final SharedPreferences prefs) {
|
||||||
final ResearchLogger researchLogger = getInstance();
|
final ResearchLogger researchLogger = getInstance();
|
||||||
|
if (researchLogger.mInFeedbackDialog) {
|
||||||
|
researchLogger.saveLogsForFeedback();
|
||||||
|
}
|
||||||
researchLogger.start();
|
researchLogger.start();
|
||||||
if (editorInfo != null) {
|
if (editorInfo != null) {
|
||||||
final Context context = researchLogger.mContext;
|
final Context context = researchLogger.mContext;
|
||||||
|
@ -688,6 +744,20 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
|
||||||
researchLogger.onWordComplete(scrubbedWord);
|
researchLogger.onWordComplete(scrubbedWord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String[] EVENTKEYS_USER_FEEDBACK = {
|
||||||
|
"UserFeedback", "FeedbackContents"
|
||||||
|
};
|
||||||
|
|
||||||
|
private void userFeedback(ResearchLog researchLog, String feedbackContents) {
|
||||||
|
// this method is special; it directs the feedbackContents to a particular researchLog
|
||||||
|
final LogUnit logUnit = new LogUnit();
|
||||||
|
final Object[] values = {
|
||||||
|
feedbackContents
|
||||||
|
};
|
||||||
|
logUnit.addLogAtom(EVENTKEYS_USER_FEEDBACK, values, false);
|
||||||
|
researchLog.publishAllEvents(logUnit);
|
||||||
|
}
|
||||||
|
|
||||||
// Regular logging methods
|
// Regular logging methods
|
||||||
|
|
||||||
private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = {
|
private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = {
|
||||||
|
|
Loading…
Reference in a new issue