Changes from Jakub

This commit is contained in:
Philipp Crocoll 2014-12-03 06:48:05 +01:00
parent df79cbaedb
commit 4ab8894503
10 changed files with 612 additions and 268 deletions

View File

@ -14,13 +14,12 @@
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="keepass2android.plugin.inputstick.MainActivity"
android:name=".MainActivity"
android:label="@string/app_name" >
</activity>
<receiver
android:name="keepass2android.plugin.inputstick.AccessReceiver"
android:name=".AccessReceiver"
android:exported="true" >
<intent-filter>
<action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
@ -29,7 +28,7 @@
</intent-filter>
</receiver>
<receiver
android:name="keepass2android.plugin.inputstick.ActionReceiver"
android:name=".ActionReceiver"
android:exported="true" >
<intent-filter>
<action android:name="keepass2android.ACTION_OPEN_ENTRY" />
@ -40,18 +39,25 @@
</receiver>
<service
android:name="keepass2android.plugin.inputstick.InputStickService"
android:name=".InputStickService"
android:enabled="true" >
</service>
<activity
android:name="keepass2android.plugin.inputstick.SettingsActivity"
android:name=".SettingsActivity"
android:label="@string/title_activity_settings" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MaskedPasswordActivity"
android:label="@string/title_activity_masked_password"
android:excludeFromRecents="true"
android:theme="@android:style/Theme.Dialog" >
</activity>
</application>
</manifest>

View File

@ -7,17 +7,27 @@
package com.inputstick.api;
public final class R {
public static final class dimen {
public static final int activity_horizontal_margin = 0x7f060000;
public static final int activity_vertical_margin = 0x7f060001;
}
public static final class drawable {
public static final int ic_launcher = 0x7f020000;
}
public static final class id {
public static final int action_settings = 0x7f0b001d;
}
public static final class menu {
public static final int install_utility = 0x7f0a0000;
}
public static final class string {
public static final int action_settings = 0x7f060002;
public static final int app_name = 0x7f060000;
public static final int hello_world = 0x7f060003;
public static final int title_activity_install_utility = 0x7f060001;
public static final int action_settings = 0x7f070002;
public static final int app_name = 0x7f070000;
public static final int hello_world = 0x7f070003;
public static final int title_activity_install_utility = 0x7f070001;
}
public static final class style {
public static final int AppBaseTheme = 0x7f070000;
public static final int AppTheme = 0x7f070001;
public static final int AppBaseTheme = 0x7f080000;
public static final int AppTheme = 0x7f080001;
}
}

View File

@ -9,8 +9,8 @@ package keepass2android.plugin.inputstick;
public final class R {
public static final class array {
public static final int layout_names=0x7f080000;
public static final int layout_values=0x7f080001;
public static final int layout_names=0x7f090000;
public static final int layout_values=0x7f090001;
}
public static final class attr {
}
@ -21,6 +21,11 @@ public final class R {
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
Default screen margins, per the Android Design guidelines.
Customize dimensions originally defined in res/values/dimens.xml (such as
screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
Default screen margins, per the Android Design guidelines.
Example customization of dimensions originally defined in res/values/dimens.xml
@ -28,43 +33,104 @@ public final class R {
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
*/
public static final int activity_horizontal_margin=0x7f050000;
public static final int activity_vertical_margin=0x7f050001;
public static final int activity_horizontal_margin=0x7f060000;
public static final int activity_vertical_margin=0x7f060001;
}
public static final class drawable {
public static final int ic_launcher=0x7f020000;
public static final int ic_notification=0x7f020001;
}
public static final class id {
public static final int action_settings=0x7f0a0003;
public static final int button1=0x7f0a0001;
public static final int button2=0x7f0a0002;
public static final int container=0x7f0a0000;
public static final int LinearLayout1=0x7f0b0016;
public static final int RelativeLayout1=0x7f0b0001;
public static final int action_settings=0x7f0b001d;
public static final int button1=0x7f0b001b;
public static final int button2=0x7f0b001c;
public static final int buttonChar1=0x7f0b0005;
public static final int buttonChar10=0x7f0b000e;
public static final int buttonChar11=0x7f0b000f;
public static final int buttonChar12=0x7f0b0010;
public static final int buttonChar13=0x7f0b0011;
public static final int buttonChar14=0x7f0b0012;
public static final int buttonChar15=0x7f0b0013;
public static final int buttonChar16=0x7f0b0014;
public static final int buttonChar2=0x7f0b0006;
public static final int buttonChar3=0x7f0b0007;
public static final int buttonChar4=0x7f0b0008;
public static final int buttonChar5=0x7f0b0009;
public static final int buttonChar6=0x7f0b000a;
public static final int buttonChar7=0x7f0b000b;
public static final int buttonChar8=0x7f0b000c;
public static final int buttonChar9=0x7f0b000d;
public static final int buttonNext=0x7f0b0004;
public static final int buttonPrev=0x7f0b0002;
public static final int checkBoxAutoConnect=0x7f0b0017;
public static final int checkBoxShowPassword=0x7f0b0015;
public static final int container=0x7f0b0000;
public static final int linearLayout1=0x7f0b0003;
public static final int radioButtonPrimary=0x7f0b0019;
public static final int radioButtonSecondary=0x7f0b001a;
public static final int radioGroup1=0x7f0b0018;
}
public static final class layout {
public static final int activity_main=0x7f030000;
public static final int fragment_main=0x7f030001;
public static final int activity_masked_password=0x7f030001;
public static final int activity_quick_settings=0x7f030002;
public static final int fragment_main=0x7f030003;
}
public static final class menu {
public static final int main=0x7f090000;
public static final int install_utility=0x7f0a0000;
public static final int main=0x7f0a0001;
}
public static final class raw {
public static final int changelog=0x7f050000;
}
public static final class string {
public static final int action_input_stick=0x7f060007;
public static final int action_settings=0x7f060002;
public static final int action_type_enter=0x7f060009;
public static final int action_type_tab=0x7f060008;
public static final int action_type_user_tab_pass_enter=0x7f06000a;
public static final int app_name=0x7f060000;
public static final int action_input_stick=0x7f070007;
public static final int action_masked_password=0x7f07000e;
public static final int action_open_settings=0x7f07000d;
public static final int action_quick_settings=0x7f07000c;
public static final int action_settings=0x7f070002;
public static final int action_type_enter=0x7f070009;
public static final int action_type_tab=0x7f070008;
public static final int action_type_user_tab_pass=0x7f07000a;
public static final int action_type_user_tab_pass_enter=0x7f07000b;
public static final int app_name=0x7f070000;
public static final int autoconnect_summary=0x7f070024;
public static final int autoconnect_title=0x7f070023;
public static final int changelog_full_title=0x7f070013;
public static final int changelog_ok_button=0x7f070015;
public static final int changelog_show_full=0x7f070016;
public static final int changelog_title=0x7f070014;
public static final int configuration_message=0x7f070012;
public static final int configuration_title=0x7f070011;
/** Strings related to Settings
*/
public static final int configure_plugin=0x7f06000c;
public static final int hello_world=0x7f060003;
public static final int kp2aplugin_author=0x7f060006;
public static final int kp2aplugin_shortdesc=0x7f060005;
public static final int kp2aplugin_title=0x7f060004;
public static final int layout_title=0x7f06000d;
public static final int title_activity_install_utility=0x7f060001;
public static final int title_activity_settings=0x7f06000b;
public static final int configure_plugin=0x7f070018;
public static final int connection_settings_title=0x7f07001b;
public static final int enable_secondary_layout_title=0x7f07001f;
public static final int enter_after_url_title=0x7f070022;
public static final int hello_world=0x7f070003;
public static final int kp2aplugin_author=0x7f070006;
public static final int kp2aplugin_shortdesc=0x7f070005;
public static final int kp2aplugin_title=0x7f070004;
public static final int layout_title=0x7f07001d;
public static final int secondary_layout_title=0x7f07001e;
public static final int show_changelog_title=0x7f070019;
public static final int show_masked_title=0x7f070028;
public static final int show_quick_settings_title=0x7f07002a;
public static final int show_secondary_summary=0x7f070021;
public static final int show_secondary_title=0x7f070020;
public static final int show_settings_title=0x7f070029;
public static final int show_tab_enter_title=0x7f070025;
public static final int show_user_pass_enter_title=0x7f070027;
public static final int show_user_pass_title=0x7f070026;
public static final int title_activity_init=0x7f070010;
public static final int title_activity_install_utility=0x7f070001;
public static final int title_activity_masked_password=0x7f07000f;
public static final int title_activity_settings=0x7f070017;
public static final int typing_settings_title=0x7f07001a;
public static final int ui_settings_title=0x7f07001c;
}
public static final class style {
/**
@ -128,7 +194,7 @@ public final class R {
API 14 theme customizations can go here.
*/
public static final int AppBaseTheme=0x7f070000;
public static final int AppBaseTheme=0x7f080000;
/** Application theme.
All customizations that are NOT specific to a particular API-level can go here.
Application theme.
@ -136,7 +202,7 @@ public final class R {
Application theme.
All customizations that are NOT specific to a particular API-level can go here.
*/
public static final int AppTheme=0x7f070001;
public static final int AppTheme=0x7f080001;
}
public static final class xml {
public static final int pref_general=0x7f040000;

View File

@ -8,17 +8,17 @@ package keepass2android.pluginsdk;
public final class R {
public static final class dimen {
public static final int activity_horizontal_margin = 0x7f050000;
public static final int activity_vertical_margin = 0x7f050001;
public static final int activity_horizontal_margin = 0x7f060000;
public static final int activity_vertical_margin = 0x7f060001;
}
public static final class drawable {
public static final int ic_launcher = 0x7f020000;
}
public static final class string {
public static final int app_name = 0x7f060000;
public static final int app_name = 0x7f070000;
}
public static final class style {
public static final int AppBaseTheme = 0x7f070000;
public static final int AppTheme = 0x7f070001;
public static final int AppBaseTheme = 0x7f080000;
public static final int AppTheme = 0x7f080001;
}
}

View File

@ -2,16 +2,28 @@
<resources>
<string name="app_name">InputStick Plugin for KP2A</string>
<string name="action_settings">Settings</string>
<string name="kp2aplugin_title">InputStick Plugin</string>
<string name="kp2aplugin_shortdesc">Allows to send text from KP2A via InputStick to your PC.</string>
<string name="kp2aplugin_author">Philipp Crocoll</string>
<string name="action_input_stick">Type with InputStick</string>
<string name="action_type_tab">Type Tab with InputStick</string>
<string name="action_type_enter">Type Enter with InputStick</string>
<string name="action_type_user_tab_pass_enter">Type username/password with InputStick</string>
<string name="action_type_user_tab_pass">Type username/password with InputStick</string>
<string name="action_type_user_tab_pass_enter">Type username/password/enter with InputStick</string>
<string name="action_quick_settings">(InputStick) Quick settings</string>
<string name="action_open_settings">(InputStick) Settings</string>
<string name="action_masked_password">(InputStick) Masked Password</string>
<string name="title_activity_masked_password">Type Masked Password</string>
<string name="title_activity_init">Plugin Init</string>
<string name="configuration_title">Plugin Configuration</string>
<string name="configuration_message">Please take a minute to configure the plugin.\n\nConfigure as plugin -> Accept\n\nMake sure that host keyboard layout matches the one used by USB host (your PC).\nEnable and set secondary layout if you work with different keyboard layouts.\n\nENABLE autoconnect if InputStick is used most of the time. Application will try to connect to InputStick everytime entry is opened.\nDISABLE autoconnect when InputStick is used occasionally. Application will not connect unless you request typing.\n\nRemember: this plugin requires InputStickUtility app to be installed.</string>
<string name="changelog_full_title">Change Log</string>
<string name="changelog_title">What\'s New</string>
<string name="changelog_ok_button">OK</string>
<string name="changelog_show_full">more...</string>
</resources>

View File

@ -4,34 +4,77 @@
<!-- Strings related to Settings -->
<string name="configure_plugin">Configure as plugin</string>
<string name="show_changelog_title">Show changelog</string>
<string name="typing_settings_title">USB host keyboard layout settings</string>
<string name="connection_settings_title">InputStick connection settings</string>
<string name="ui_settings_title">UI settings</string>
<string name="layout_title">Host keyboard layout</string>
<string name="layout_title">Host keyboard layout (primary)</string>
<string name="secondary_layout_title">Host keyboard layout (secondary)</string>
<string name="enable_secondary_layout_title">Enable secondary layout</string>
<string name="show_secondary_title">Enable secondary layout</string>
<string name="show_secondary_summary">When enabled, both layouts options will be shown for each entry and field.\nNOTE: will take effect after entry is reloaded!</string>
<string name="enter_after_url_title">Always add Enter after typing URL</string>
<string name="autoconnect_title">InputStick autoconnect</string>
<string name="autoconnect_summary">Connect to InputStick every time entry is opened. If not checked, connection will be established before typing OR after entry is opened, but only if typing action was used within last 10min.\nENABLE - when InputStick is used most of the time.\nDISABLE - when InputStick is used occasionally</string>
<string name="show_tab_enter_title">Show Tab and Enter actions</string>
<string name="show_user_pass_title">Show username/password shortcut</string>
<string name="show_user_pass_enter_title">Show username/password/enter shortcut</string>
<string name="show_masked_title">Show Masked Password shortcut</string>
<string name="show_settings_title">Show Settings shortcut</string>
<string name="show_quick_settings_title">Show Tab and Enter actions</string>
<string-array name="layout_names">
<item>English (US)</item>
<item>Danish</item>
<item>English (US)</item>
<item>English (UK)</item>
<item>Finnish</item>
<item>French</item>
<item>French (Swiss)</item>
<item>German</item>
<item>German (Mac)</item>
<item>German (Swiss)</item>
<item>Hebrew</item>
<item>Italian</item>
<item>Norwegian</item>
<item>Polish</item>
<item>Portuguese (BR)</item>
<item>Russian</item>
<item>Slovak</item>
<item>Portuguese (BR)</item>
<item>Norwegian</item>
<item>Swedish</item>
<item>French</item>
<item>Spanish</item>
<item>Swedish</item>
<item>English (Dvorak)</item>
</string-array>
<string-array name="layout_values">
<item>en-US</item>
<item>da-DK</item>
<item>en-US</item>
<item>en-GB</item>
<item>fi-FI</item>
<item>fr-FR</item>
<item>fr-CH</item>
<item>de-DE</item>
<item>de-DE-mac</item>
<item>de-CH</item>
<item>he-IL</item>
<item>it-IT</item>
<item>nb-NO</item>
<item>pl-PL</item>
<item>pt-BR</item>
<item>ru-RU</item>
<item>sk-SK</item>
<item>pt-BR</item>
<item>nb-NO</item>
<item>sv-SE</item>
<item>fr-FR</item>
<item>es-ES</item>
<item>sv-SE</item>
<item>en-DV</item>
</string-array>

View File

@ -1,24 +1,93 @@
<PreferenceScreen
android:key="general_pref"
xmlns:android="http://schemas.android.com/apk/res/android" >
<Preference
android:key="enable_plugin_pref"
android:title="@string/configure_plugin" />
<!--
NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
dismiss it.
-->
<!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
<ListPreference
android:defaultValue="en-US"
android:entries="@array/layout_names"
android:entryValues="@array/layout_values"
android:key="kbd_layout"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="@string/layout_title" />
</PreferenceScreen>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="general_pref" >
<Preference
android:key="enable_plugin_pref"
android:title="@string/configure_plugin" />
<Preference
android:key="show_changelog_preference_key"
android:title="@string/show_changelog_title" >
</Preference>
<!--
NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
dismiss it.
-->
<!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
<PreferenceCategory android:title="@string/typing_settings_title" >
<ListPreference
android:defaultValue="en-US"
android:entries="@array/layout_names"
android:entryValues="@array/layout_values"
android:key="kbd_layout"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="@string/layout_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="show_secondary"
android:summary="@string/show_secondary_summary"
android:title="@string/show_secondary_title" />
<ListPreference
android:defaultValue="en-US"
android:entries="@array/layout_names"
android:entryValues="@array/layout_values"
android:key="secondary_kbd_layout"
android:negativeButtonText="@null"
android:positiveButtonText="@null"
android:title="@string/secondary_layout_title" />
<CheckBoxPreference
android:defaultValue="false"
android:key="enter_after_url"
android:title="@string/enter_after_url_title" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/connection_settings_title" >
<CheckBoxPreference
android:defaultValue="true"
android:key="autoconnect"
android:summary="@string/autoconnect_summary"
android:title="@string/autoconnect_title" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/ui_settings_title" >
<CheckBoxPreference
android:defaultValue="true"
android:key="show_tab_enter"
android:title="@string/show_tab_enter_title" />
<CheckBoxPreference
android:defaultValue="true"
android:key="show_user_pass"
android:title="@string/show_user_pass_title" />
<CheckBoxPreference
android:defaultValue="true"
android:key="show_user_pass_enter"
android:title="@string/show_user_pass_enter_title" />
<CheckBoxPreference
android:defaultValue="true"
android:key="show_masked"
android:title="@string/show_masked_title" />
<CheckBoxPreference
android:defaultValue="true"
android:key="show_settings"
android:title="@string/show_settings_title" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -3,91 +3,240 @@ package keepass2android.plugin.inputstick;
import keepass2android.pluginsdk.KeepassDefs;
import keepass2android.pluginsdk.PluginAccessException;
import keepass2android.pluginsdk.Strings;
import org.json.JSONObject;
import sheetrock.panda.changelog.ChangeLog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
public class ActionReceiver extends keepass2android.pluginsdk.PluginActionBroadcastReceiver {
private static final String EXTRA_TEXT = "text";
private static final String ACTION_MASKED_PASSWORD = "masked_password";
private static final String ACTION_SETTINGS = "settings";
private static final String ACTION_USER_PASS = "user_pass";
private static final String ACTION_USER_PASS_ENTER = "user_pass_enter";
private static final int IC = R.drawable.ic_launcher;
private static long lastTypingTime = 0;
private static final long AUTOCONNECT_TIMEOUT = 600000; //10min,
private static boolean enterAfterURL;
@Override
protected void openEntry(OpenEntryAction oe) {
try {
for (String field: oe.getEntryFields().keySet())
{
oe.addEntryFieldAction("keepass2android.plugin.inputstick.type", Strings.PREFIX_STRING+field, oe.getContext().getString(R.string.action_input_stick),
R.drawable.ic_launcher, null);
Context ctx = oe.getContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
try {
enterAfterURL = prefs.getBoolean("enter_after_url", true);
boolean showSecondary = prefs.getBoolean("show_secondary", false);
String layoutPrimary = prefs.getString("kbd_layout", "en-US");
String layoutSecondary = prefs.getString("secondary_kbd_layout", "en-US");
Bundle b;
String displayText;
for (String field: oe.getEntryFields().keySet()) {
displayText = ctx.getString(R.string.action_input_stick);
if (showSecondary) {
displayText += " (" + layoutPrimary + ")";
}
b = new Bundle();
b.putString(Const.EXTRA_LAYOUT, layoutPrimary);
oe.addEntryFieldAction("keepass2android.plugin.inputstick.type", Strings.PREFIX_STRING + field, displayText, IC, b);
if (showSecondary) {
displayText = oe.getContext().getString(R.string.action_input_stick) + " (" + layoutSecondary + ")";
b = new Bundle();
b.putString(Const.EXTRA_LAYOUT, layoutSecondary);
oe.addEntryFieldAction("keepass2android.plugin.inputstick.typesecondary", Strings.PREFIX_STRING + field, displayText, IC, b);
}
}
Bundle b1 = new Bundle();
b1.putString(EXTRA_TEXT, "\t");
oe.addEntryAction(oe.getContext().getString(R.string.action_type_tab), R.drawable.ic_launcher, b1);
Bundle b2 = new Bundle();
b2.putString(EXTRA_TEXT, "\n");
oe.addEntryAction(oe.getContext().getString(R.string.action_type_enter), R.drawable.ic_launcher, b2);
Bundle b3 = new Bundle();
b3.putString(EXTRA_TEXT, "user_pass");
oe.addEntryAction(oe.getContext().getString(R.string.action_type_user_tab_pass_enter), R.drawable.ic_launcher, b3);
if (prefs.getBoolean("show_tab_enter", true)) {
b = new Bundle();
b.putString(Const.EXTRA_TEXT, "\t");
oe.addEntryAction(ctx.getString(R.string.action_type_tab), IC, b);
b = new Bundle();
b.putString(Const.EXTRA_TEXT, "\n");
oe.addEntryAction(ctx.getString(R.string.action_type_enter), IC, b);
}
if (prefs.getBoolean("show_user_pass", true)) {
displayText = ctx.getString(R.string.action_type_user_tab_pass);
if (showSecondary) {
displayText += " (" + layoutPrimary + ")";
}
b = new Bundle();
b.putString(Const.EXTRA_TEXT, ACTION_USER_PASS);
b.putString(Const.EXTRA_LAYOUT, layoutPrimary);
oe.addEntryAction(displayText, IC, b);
if (showSecondary) {
displayText = oe.getContext().getString(R.string.action_type_user_tab_pass) + " (" + layoutSecondary + ")";
b = new Bundle();
b.putString(Const.EXTRA_TEXT, ACTION_USER_PASS);
b.putString(Const.EXTRA_LAYOUT, layoutSecondary);
oe.addEntryAction(displayText, IC, b);
}
}
if (prefs.getBoolean("show_user_pass_enter", false)) {
displayText = ctx.getString(R.string.action_type_user_tab_pass_enter);
if (showSecondary) {
displayText += " (" + layoutPrimary + ")";
}
b = new Bundle();
b.putString(Const.EXTRA_TEXT, ACTION_USER_PASS_ENTER);
b.putString(Const.EXTRA_LAYOUT, layoutPrimary);
oe.addEntryAction(displayText, IC, b);
if (showSecondary) {
displayText = oe.getContext().getString(R.string.action_type_user_tab_pass_enter) + " (" + layoutSecondary + ")";
b = new Bundle();
b.putString(Const.EXTRA_TEXT, ACTION_USER_PASS_ENTER);
b.putString(Const.EXTRA_LAYOUT, layoutSecondary);
oe.addEntryAction(displayText, IC, b);
}
}
if (prefs.getBoolean("show_masked", true)) {
displayText = ctx.getString(R.string.action_masked_password);
if (showSecondary) {
displayText += " (" + layoutPrimary + ")";
}
b = new Bundle();
b.putString(Const.EXTRA_TEXT, ACTION_MASKED_PASSWORD);
b.putString(Const.EXTRA_LAYOUT, layoutPrimary);
oe.addEntryAction(displayText, IC, b);
if (showSecondary) {
displayText = oe.getContext().getString(R.string.action_masked_password) + " (" + layoutSecondary + ")";
b = new Bundle();
b.putString(Const.EXTRA_TEXT, ACTION_MASKED_PASSWORD);
b.putString(Const.EXTRA_LAYOUT, layoutSecondary);
oe.addEntryAction(displayText, IC, b);
}
}
if (prefs.getBoolean("show_settings", true)) {
b = new Bundle();
b.putString(Const.EXTRA_TEXT, ACTION_SETTINGS);
oe.addEntryAction(ctx.getString(R.string.action_open_settings), IC, b);
}
} catch (PluginAccessException e) {
e.printStackTrace();
}
//typeText(oe.getContext(), "");
//typeText(oe.getContext(), "en-US");
if (prefs.getBoolean("autoconnect", true)) {
typeText(ctx, "", "en-US");
} else {
if ((lastTypingTime != 0) && ((System.currentTimeMillis() - AUTOCONNECT_TIMEOUT) < lastTypingTime)) {
//System.out.println("AUTOCONNECT (NO TIMEOUT)");
typeText(ctx, "", "en-US");
}
}
ChangeLog cl = new ChangeLog(ctx.getApplicationContext());
if (cl.firstRun()) {
Intent i = new Intent(ctx.getApplicationContext(), SettingsActivity.class);
i.putExtra(Const.EXTRA_CHANGELOG, true);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.getApplicationContext().startActivity(i);
}
}
@Override
protected void closeEntryView(CloseEntryViewAction closeEntryView)
{
protected void closeEntryView(CloseEntryViewAction closeEntryView) {
Intent serviceIntent = new Intent(closeEntryView.getContext(), InputStickService.class);
serviceIntent.setAction(InputStickService.DISCONNECT);
closeEntryView.getContext().startService(serviceIntent);
//System.out.println("CLOSE ENTRY");
};
@Override
protected void actionSelected(ActionSelectedAction actionSelected) {
if (actionSelected.isEntryAction())
{
String text = actionSelected.getActionData().getString(EXTRA_TEXT);
if ("user_pass".equals(text))
{
typeText(actionSelected.getContext(),
actionSelected.getEntryFields().get(KeepassDefs.UserNameField));
typeText(actionSelected.getContext(), "\t");
typeText(actionSelected.getContext(), actionSelected.getEntryFields().get(KeepassDefs.PasswordField));
typeText(actionSelected.getContext(), "\n");
Context ctx = actionSelected.getContext();
String layoutName = actionSelected.getActionData().getString(Const.EXTRA_LAYOUT, "en-US");
if (actionSelected.isEntryAction()) {
String text = actionSelected.getActionData().getString(Const.EXTRA_TEXT);
if (ACTION_MASKED_PASSWORD.equals(text)) {
typeText(ctx, "", "en-US"); //will connect if not already connected
Intent i = new Intent(ctx.getApplicationContext(), MaskedPasswordActivity.class);
i.putExtra(Const.EXTRA_TEXT, actionSelected.getEntryFields().get(KeepassDefs.PasswordField));
i.putExtra(Const.EXTRA_LAYOUT, layoutName);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.getApplicationContext().startActivity(i);
} else if (ACTION_SETTINGS.equals(text)) {
Intent i = new Intent(ctx.getApplicationContext(), SettingsActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.getApplicationContext().startActivity(i);
} else if (ACTION_USER_PASS.equals(text)) {
typeText(ctx, actionSelected.getEntryFields().get(KeepassDefs.UserNameField), layoutName);
typeText(ctx, "\t", layoutName);
typeText(ctx, actionSelected.getEntryFields().get(KeepassDefs.PasswordField), layoutName);
} else if (ACTION_USER_PASS_ENTER.equals(text)) {
typeText(ctx, actionSelected.getEntryFields().get(KeepassDefs.UserNameField), layoutName);
typeText(ctx, "\t", layoutName);
typeText(ctx, actionSelected.getEntryFields().get(KeepassDefs.PasswordField), layoutName);
typeText(ctx, "\n", layoutName);
} else {
typeText(ctx, text, layoutName);
}
else
{
typeText(actionSelected.getContext(), text);
}
}
else
{
String fieldKey =actionSelected.getFieldId().substring(Strings.PREFIX_STRING.length());
} else {
String fieldKey = actionSelected.getFieldId().substring(Strings.PREFIX_STRING.length());
String text = actionSelected.getEntryFields().get(fieldKey);
typeText(actionSelected.getContext(), text);
typeText(ctx, text, layoutName);
if ((enterAfterURL) && ("URL".equals(fieldKey))) {
typeText(ctx, "\n", layoutName);
}
}
}
private void typeText(Context ctx, String text) {
private void typeText(Context ctx, String text, String layout) {
lastTypingTime = System.currentTimeMillis();
Intent serviceIntent = new Intent(ctx, InputStickService.class);
serviceIntent.setAction(InputStickService.TYPE);
serviceIntent.putExtra(Intent.EXTRA_TEXT, text);
ctx.startService(serviceIntent);
Bundle b = new Bundle();
b.putString(Const.EXTRA_TEXT, text);
b.putString(Const.EXTRA_LAYOUT, layout);
serviceIntent.putExtras(b);
ctx.startService(serviceIntent);
}
@Override
protected void entryOutputModified(EntryOutputModifiedAction eom) {
Context ctx = eom.getContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
try {
eom.addEntryFieldAction("keepass2android.plugin.inputstick.type", eom.getModifiedFieldId(), eom.getContext().getString(R.string.action_input_stick),
R.drawable.ic_launcher, null);
boolean showSecondary = prefs.getBoolean("show_secondary", false);
String layoutPrimary = prefs.getString("kbd_layout", "en-US");
String layoutSecondary = prefs.getString("secondary_kbd_layout", "en-US");
Bundle b;
String displayText;
displayText = ctx.getString(R.string.action_input_stick);
if (showSecondary) {
displayText += " (" + layoutPrimary + ")";
}
b = new Bundle();
b.putString(Const.EXTRA_LAYOUT, layoutPrimary);
eom.addEntryFieldAction("keepass2android.plugin.inputstick.type", eom.getModifiedFieldId(), displayText, IC, null);
if (showSecondary) {
displayText = ctx.getString(R.string.action_input_stick) + " (" + layoutSecondary + ")";
b = new Bundle();
b.putString(Const.EXTRA_LAYOUT, layoutSecondary);
eom.addEntryFieldAction("keepass2android.plugin.inputstick.typesecondary", eom.getModifiedFieldId(), displayText, IC, null);
}
} catch (PluginAccessException e) {
e.printStackTrace();
}

View File

@ -2,6 +2,14 @@ package keepass2android.plugin.inputstick;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import com.inputstick.api.ConnectionManager;
import com.inputstick.api.InputStickStateListener;
import com.inputstick.api.basic.InputStickHID;
@ -9,31 +17,33 @@ import com.inputstick.api.basic.InputStickKeyboard;
import com.inputstick.api.hid.HIDKeycodes;
import com.inputstick.api.layout.KeyboardLayout;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat.Builder;
import android.util.Log;
import android.widget.Toast;
public class InputStickService extends Service implements InputStickStateListener {
private class ItemToType {
public String mText;
public String mLayout;
ItemToType(String text, String layout) {
mText = text;
mLayout = layout;
}
public void type() {
typeString(mText, mLayout);
}
}
private ArrayList<ItemToType> items = new ArrayList<ItemToType>();
private static final String _TAG = "KP2AINPUTSTICK";
public static final String DISCONNECT = "disconnect";
private static final int NOTIFICATION_ID = 1;
public static final String TYPE = "type";
private static final String TYPE_QUEUE = "type_queue";
@Override
public void onCreate() {
InputStickHID.addStateListener(this);
super.onCreate();
}
private ArrayList<String> stringsToType = new ArrayList<String>();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
@ -43,129 +53,91 @@ public class InputStickService extends Service implements InputStickStateListene
else
Log.d(_TAG, "starting with null intent");
if (DISCONNECT.equals(intent.getAction()))
{
if (DISCONNECT.equals(intent.getAction())) {
Log.d(_TAG, "disconnecting");
try
{
InputStickHID.disconnect();
}
catch (NullPointerException e)
{
try {
int state = InputStickHID.getState();
switch (state) {
case ConnectionManager.STATE_CONNECTED:
case ConnectionManager.STATE_CONNECTING:
case ConnectionManager.STATE_READY:
InputStickHID.disconnect();
break;
case ConnectionManager.STATE_DISCONNECTED:
case ConnectionManager.STATE_FAILURE:
break;
default:
InputStickHID.disconnect();
}
} catch (NullPointerException e) {
Log.d(_TAG, "couldn't disconnect. Probably we never connected.");
}
stopSelf();
return Service.START_NOT_STICKY;
}
showNotification();
if (TYPE_QUEUE.equals(intent.getAction()))
{
typeQueue();
}
if (TYPE.equals(intent.getAction()))
{
int state = InputStickHID.getState();
String stringToType = intent.getStringExtra(Intent.EXTRA_TEXT);
if (TYPE.equals(intent.getAction())) {
int state = InputStickHID.getState();
String stringToType = intent.getStringExtra(Const.EXTRA_TEXT);
String layoutToUse = intent.getStringExtra(Const.EXTRA_LAYOUT);
switch (state) {
case ConnectionManager.STATE_CONNECTED:
case ConnectionManager.STATE_CONNECTING:
synchronized (items) {
items.add(new ItemToType(stringToType, layoutToUse));
}
break;
case ConnectionManager.STATE_READY:
typeString(stringToType);
typeString(stringToType, layoutToUse);
break;
case ConnectionManager.STATE_DISCONNECTED:
case ConnectionManager.STATE_FAILURE:
synchronized (stringsToType) {
stringsToType.add(stringToType);
}
synchronized (items) {
items.add(new ItemToType(stringToType, layoutToUse));
}
Log.d(_TAG, "trigger connect");
InputStickHID.connect(getApplication());
break;
}
}
}
return Service.START_NOT_STICKY;
}
private void typeString(String stringToType) {
Log.d(_TAG, "typing "+stringToType);
if (stringToType.equals("\n"))
{
InputStickKeyboard.pressAndRelease(HIDKeycodes.NONE, HIDKeycodes.KEY_ENTER);
return;
private void typeString(String stringToType, String layoutToUse) {
if (InputStickHID.getState() == ConnectionManager.STATE_READY) {
Log.d(_TAG, "typing "+stringToType + " @ " + layoutToUse);
if (stringToType.equals("\n")) {
InputStickKeyboard.pressAndRelease(HIDKeycodes.NONE, HIDKeycodes.KEY_ENTER);
return;
} else if (stringToType.equals("\t")) {
InputStickKeyboard.pressAndRelease(HIDKeycodes.NONE, HIDKeycodes.KEY_TAB);
return;
} else {
KeyboardLayout l = KeyboardLayout.getLayout(layoutToUse);
l.type(stringToType);
}
} else {
Log.d(_TAG, "typing NOT READY");
}
if (stringToType.equals("\t"))
{
InputStickKeyboard.pressAndRelease(HIDKeycodes.NONE, HIDKeycodes.KEY_TAB);
return;
}
KeyboardLayout layout = KeyboardLayout.getLayout(PreferenceManager.getDefaultSharedPreferences(this).getString("kbd_layout", "en-US"));
//currently supported layouts: de-DE, en-US, pl-PL, ru-RU
layout.type(stringToType);
//InputStickKeyboard.typeASCII(stringToType);
}
private void typeQueue() {
synchronized (stringsToType) {
for (String t:stringsToType)
synchronized (items) {
for (ItemToType itt : items)
{
Log.d(_TAG, "typing (after callback) "+t);
typeString(t);
Log.d(_TAG, "typing (after callback) " + itt.mText);
itt.type();
}
stringsToType.clear();
items.clear();
}
}
private void showNotification() {
android.support.v4.app.NotificationCompat.Builder b = new Builder(this);
b.setSmallIcon(R.drawable.ic_notification);
b.setPriority(android.support.v4.app.NotificationCompat.PRIORITY_MIN);
b.setContentTitle("KP2A InputStick");
int state = InputStickHID.getState();
Intent disconnectIntent = new Intent(this, InputStickService.class);
disconnectIntent.setAction(DISCONNECT);
switch (state) {
case ConnectionManager.STATE_CONNECTED:
case ConnectionManager.STATE_CONNECTING:
b.setContentText("connecting...");
b.addAction(android.R.drawable.ic_menu_close_clear_cancel, "disconnect", PendingIntent.getService(this, 1, disconnectIntent, 0));
break;
case ConnectionManager.STATE_READY:
b.setContentText("InputStick connected.");
b.addAction(android.R.drawable.ic_menu_close_clear_cancel, "disconnect", PendingIntent.getService(this, 1, disconnectIntent, 0));
break;
case ConnectionManager.STATE_DISCONNECTED:
case ConnectionManager.STATE_FAILURE:
b.setContentText("InputStick failure");
break;
}
startForeground(NOTIFICATION_ID, b.build());
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@ -177,11 +149,9 @@ public class InputStickService extends Service implements InputStickStateListene
@Override
public void onStateChanged(int state) {
showNotification();
Log.d(_TAG, "state changed: "+state);
switch (state) {
case ConnectionManager.STATE_READY:
case ConnectionManager.STATE_READY:
/*
Intent typeQueue = new Intent(this, InputStickService.class);
typeQueue.setAction(TYPE_QUEUE);
@ -190,16 +160,13 @@ public class InputStickService extends Service implements InputStickStateListene
new AsyncTask<Object, Object, Object>() {
@Override
protected Object doInBackground(Object... params) {
protected Object doInBackground(Object... params) {
try {
Thread.sleep(1000, 0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
typeQueue();
typeQueue();
return null;
}
@ -213,8 +180,13 @@ public class InputStickService extends Service implements InputStickStateListene
case ConnectionManager.STATE_FAILURE:
Log.d(_TAG, "stopping service. State = "+state);
stopSelf();
Toast.makeText(this, "Failure connecting to InputStick! Do you have InputStickUtility installed?", Toast.LENGTH_LONG).show();
AlertDialog ad = InputStickHID.getDownloadDialog(this);
if (ad != null) {
//Utility application not installed
ad.show();
} else {
Toast.makeText(this, "Failure connecting to InputStick!", Toast.LENGTH_LONG).show();
}
break;
default:
break;

View File

@ -1,29 +1,23 @@
package keepass2android.plugin.inputstick;
import keepass2android.pluginsdk.AccessManager;
import keepass2android.pluginsdk.Strings;
import sheetrock.panda.changelog.ChangeLog;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;
import android.text.TextUtils;
import java.util.List;
import keepass2android.pluginsdk.AccessManager;
import keepass2android.pluginsdk.Strings;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
@ -50,6 +44,27 @@ public class SettingsActivity extends PreferenceActivity {
super.onPostCreate(savedInstanceState);
setupSimplePreferencesScreen();
if (getIntent().getBooleanExtra(Const.EXTRA_CHANGELOG, false)) {
ChangeLog cl = new ChangeLog(this);
cl.getLogDialog().show();
} else {
//first run ever?
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (prefs.getBoolean("display_configuration_message", true)) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(getString(R.string.configuration_title));
alert.setMessage(getString(R.string.configuration_message));
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//disable cfg message ONLY after clicking OK button
prefs.edit().putBoolean("display_configuration_message", false).apply();
}
});
alert.show();
}
}
}
/**
@ -69,41 +84,43 @@ public class SettingsActivity extends PreferenceActivity {
addPreferencesFromResource(R.xml.pref_general);
bindPreferenceSummaryToValue(findPreference("kbd_layout"));
bindPreferenceSummaryToValue(findPreference("secondary_kbd_layout"));
Preference enablePref = findPreference("enable_plugin_pref");
enablePref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
try
{
Intent i = new Intent(Strings.ACTION_EDIT_PLUGIN_SETTINGS);
try {
Intent i = new Intent( Strings.ACTION_EDIT_PLUGIN_SETTINGS);
i.putExtra(Strings.EXTRA_PLUGIN_PACKAGE, SettingsActivity.this.getPackageName());
startActivityForResult(i, 123);
}
catch(Exception e)
{
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
});
Preference showChangelogPref = (Preference)findPreference("show_changelog_preference_key");
showChangelogPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
ChangeLog cl = new ChangeLog(SettingsActivity.this);
cl.getFullLogDialog().show();
return true;
}
});
}
@Override
protected void onResume() {
Preference enablePref = findPreference("enable_plugin_pref");
if (AccessManager.getAllHostPackages(SettingsActivity.this).isEmpty())
{
if (AccessManager.getAllHostPackages(SettingsActivity.this).isEmpty()) {
enablePref.setSummary("");
}
else
{
} else {
enablePref.setSummary("enabled.");
}
// TODO Auto-generated method stub
super.onResume();
}