implemented AutoFill service in Java, integrated into main app

This commit is contained in:
Philipp Crocoll 2016-01-27 05:58:33 +01:00
parent c0f2b68963
commit 3d2f6db36d
28 changed files with 813 additions and 285 deletions

View File

@ -84,6 +84,10 @@ namespace keepass2android
AskAddTemplatesMessage, AskAddTemplatesMessage,
ReadOnlyReason_PreKitKat, ReadOnlyReason_PreKitKat,
ReadOnlyReason_ReadOnlyFlag, ReadOnlyReason_ReadOnlyFlag,
ReadOnlyReason_ReadOnlyKitKat ReadOnlyReason_ReadOnlyKitKat,
ActivateAutoFillService_title,
ActivateAutoFillService_message,
ActivateAutoFillService_btnKeyboard,
ActivateAutoFillService_btnAutoFill
} }
} }

View File

@ -1 +0,0 @@
#Wed Jan 13 21:02:12 CET 2016

View File

@ -34,23 +34,11 @@
</component> </component>
<component name="FileEditorManager"> <component name="FileEditorManager">
<leaf> <leaf>
<file leaf-file-name="LatinKeyboardBaseView.java" pinned="false" current-in-tab="false"> <file leaf-file-name="KP2AKeyboard.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardBaseView.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="1234" column="25" selection-start-line="1234" selection-start-column="25" selection-end-line="1234" selection-end-column="25" />
<folding>
<element signature="method#LatinKeyboardBaseView#1;class#LatinKeyboardBaseView#0" expanded="false" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="KP2AKeyboard.java" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="2465" column="13" selection-start-line="2465" selection-start-column="13" selection-end-line="2465" selection-end-column="13" /> <caret line="2618" column="0" selection-start-line="2618" selection-start-column="0" selection-end-line="2618" selection-end-column="0" />
<folding> <folding>
<element signature="e#17350#17396#0" expanded="true" /> <element signature="e#17350#17396#0" expanded="true" />
<element signature="e#17428#17478#0" expanded="true" /> <element signature="e#17428#17478#0" expanded="true" />
@ -97,70 +85,108 @@
</provider> </provider>
</entry> </entry>
</file> </file>
<file leaf-file-name="LocaleHelper.java" pinned="false" current-in-tab="false"> <file leaf-file-name="StringForTyping.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/LocaleHelper.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/StringForTyping.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="49" column="53" selection-start-line="49" selection-start-column="53" selection-end-line="49" selection-end-column="53" /> <caret line="2" column="13" selection-start-line="2" selection-start-column="13" selection-end-line="2" selection-end-column="13" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="build.gradle" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/build.gradle">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-4.76">
<caret line="7" column="24" selection-start-line="7" selection-start-column="24" selection-end-line="7" selection-end-column="24" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="accserviceconfig.xml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/res/xml/accserviceconfig.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="0" column="38" selection-start-line="0" selection-start-column="38" selection-end-line="0" selection-end-column="38" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="strings.xml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/res/values/strings.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-7.56">
<caret line="378" column="0" selection-start-line="378" selection-start-column="0" selection-end-line="378" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="strings_autofill.xml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/res/values/strings_autofill.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="8" column="0" selection-start-line="8" selection-start-column="0" selection-end-line="8" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="AutoFillService.java" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/autofill/AutoFillService.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.7568306">
<caret line="104" column="5" selection-start-line="104" selection-start-column="5" selection-end-line="104" selection-end-column="5" />
<folding> <folding>
<element signature="imports" expanded="true" /> <element signature="imports" expanded="true" />
<element signature="e#1549#1550#0" expanded="true" />
<element signature="e#1585#1586#0" expanded="true" />
<element signature="e#1660#1661#0" expanded="true" />
<element signature="e#1712#1713#0" expanded="true" />
<element signature="e#2880#2881#0" expanded="true" />
<element signature="e#2913#2914#0" expanded="true" />
<element signature="e#9594#9692#0" expanded="true" />
<element signature="e#9727#9793#0" expanded="true" />
<element signature="e#11813#11814#0" expanded="true" />
<element signature="e#11867#11868#0" expanded="true" />
<element signature="e#11925#11926#0" expanded="true" />
<element signature="e#11979#11980#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
</file> </file>
<file leaf-file-name="kbd_qwerty.xml" pinned="false" current-in-tab="false"> <file leaf-file-name="prefs.xml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/res/xml/kbd_qwerty.xml"> <entry file="file://$PROJECT_DIR$/app/src/main/res/xml/prefs.xml">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="476" column="38" selection-start-line="476" selection-start-column="38" selection-end-line="476" selection-end-column="38" /> <caret line="60" column="46" selection-start-line="60" selection-start-column="46" selection-end-line="60" selection-end-column="46" />
<folding> <folding>
<element signature="e#5702#5728#0" expanded="true" /> <element signature="e#2450#2474#0" expanded="true" />
<element signature="e#6920#6946#0" expanded="true" />
<element signature="e#8140#8166#0" expanded="true" />
<element signature="e#9357#9383#0" expanded="true" />
<element signature="e#10581#10607#0" expanded="true" />
<element signature="e#12082#12108#0" expanded="true" />
<element signature="e#13602#13628#0" expanded="true" />
<element signature="e#15124#15150#0" expanded="true" />
<element signature="e#16643#16669#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
</file> </file>
<file leaf-file-name="kbd_qwerty_black.xml" pinned="false" current-in-tab="false"> <file leaf-file-name="KeyboardData.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/res/xml/kbd_qwerty_black.xml"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/KeyboardData.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="-12.24">
<caret line="146" column="46" selection-start-line="146" selection-start-column="35" selection-end-line="146" selection-end-column="46" /> <caret line="18" column="30" selection-start-line="18" selection-start-column="30" selection-end-line="18" selection-end-column="30" />
<folding> <folding>
<element signature="e#5666#5692#0" expanded="true" /> <element signature="imports" expanded="true" />
<element signature="e#362#363#0" expanded="true" />
<element signature="e#404#405#0" expanded="true" />
<element signature="e#438#439#0" expanded="true" />
<element signature="e#479#480#0" expanded="true" />
</folding> </folding>
</state> </state>
</provider> </provider>
</entry> </entry>
</file> </file>
<file leaf-file-name="kbd_qwerty.xml" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/res/xml-de/kbd_qwerty.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="147" column="38" selection-start-line="147" selection-start-column="38" selection-end-line="147" selection-end-column="38" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="KeyboardSwitcher.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KeyboardSwitcher.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="591" column="0" selection-start-line="591" selection-start-column="0" selection-end-line="591" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="LatinIMESettings.java" pinned="false" current-in-tab="false"> <file leaf-file-name="LatinIMESettings.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinIMESettings.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinIMESettings.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
@ -171,35 +197,14 @@
</provider> </provider>
</entry> </entry>
</file> </file>
<file leaf-file-name="LatinKeyboardView.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardView.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="36" column="23" selection-start-line="36" selection-start-column="23" selection-end-line="36" selection-end-column="23" />
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="LatinKeyboard.java" pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinKeyboard.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="397" column="24" selection-start-line="397" selection-start-column="24" selection-end-line="397" selection-end-column="24" />
<folding>
<element signature="e#15971#15972#0" expanded="true" />
<element signature="e#16007#16008#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
</leaf> </leaf>
</component> </component>
<component name="FileTemplateManagerImpl"> <component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES"> <option name="RECENT_TEMPLATES">
<list> <list>
<option value="resourceFile" />
<option value="Class" /> <option value="Class" />
<option value="valueResourceFile" />
</list> </list>
</option> </option>
</component> </component>
@ -1228,7 +1233,7 @@
</option> </option>
<option name="modificationStamps"> <option name="modificationStamps">
<map> <map>
<entry key="$PROJECT_DIR$" value="4358048248205" /> <entry key="$PROJECT_DIR$" value="4359057111489" />
</map> </map>
</option> </option>
<option name="projectBuildClasspath"> <option name="projectBuildClasspath">
@ -1475,7 +1480,6 @@
<option name="CHANGED_PATHS"> <option name="CHANGED_PATHS">
<list> <list>
<option value="$PROJECT_DIR$/build.gradle" /> <option value="$PROJECT_DIR$/build.gradle" />
<option value="$PROJECT_DIR$/app/build.gradle" />
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardBaseView.java" /> <option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardBaseView.java" />
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LanguageSwitcher.java" /> <option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LanguageSwitcher.java" />
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/Loc.java" /> <option value="$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/Loc.java" />
@ -1483,6 +1487,12 @@
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KeyboardSwitcher.java" /> <option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KeyboardSwitcher.java" />
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/LocaleHelper.java" /> <option value="$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/LocaleHelper.java" />
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java" /> <option value="$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java" />
<option value="$PROJECT_DIR$/app/build.gradle" />
<option value="$PROJECT_DIR$/app/src/main/res/xml/accserviceconfig.xml" />
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/KeyboardData.java" />
<option value="$PROJECT_DIR$/app/src/main/java/keepass2android/autofill/AutoFillService.java" />
<option value="$PROJECT_DIR$/app/src/main/res/values/strings.xml" />
<option value="$PROJECT_DIR$/app/src/main/res/values/strings_autofill.xml" />
</list> </list>
</option> </option>
</component> </component>
@ -1558,96 +1568,6 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" /> <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT> </PATH_ELEMENT>
</PATH> </PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="java" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="KP2ASoftkeyboard_AS" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="app" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="main" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="java" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="KP2ASoftkeyboard_AS" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="app" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="main" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="java" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="keepass2android" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="softkeyboard" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="java" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="KP2ASoftkeyboard_AS" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="app" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="src" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="main" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="java" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="keepass2android" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="kbbridge" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane> </subPane>
</pane> </pane>
<pane id="Scope" /> <pane id="Scope" />
@ -1673,6 +1593,8 @@
<property name="android.project.structure.proportion" value="0.15" /> <property name="android.project.structure.proportion" value="0.15" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../KP2ASoftKeyboard2/java" /> <property name="last_opened_file_path" value="$PROJECT_DIR$/../KP2ASoftKeyboard2/java" />
<property name="FullScreen" value="false" /> <property name="FullScreen" value="false" />
<property name="OverrideImplement.combined" value="true" />
<property name="OverrideImplement.overriding.sorted" value="false" />
</component> </component>
<component name="RunManager"> <component name="RunManager">
<configuration default="true" type="AndroidRunConfigurationType" factoryName="Android Application"> <configuration default="true" type="AndroidRunConfigurationType" factoryName="Android Application">
@ -1843,34 +1765,43 @@
</task> </task>
<servers /> <servers />
</component> </component>
<component name="TodoView">
<todo-panel id="selected-file">
<is-autoscroll-to-source value="true" />
</todo-panel>
<todo-panel id="all">
<are-packages-shown value="true" />
<is-autoscroll-to-source value="true" />
</todo-panel>
</component>
<component name="ToolWindowManager"> <component name="ToolWindowManager">
<frame x="-8" y="-8" width="1382" height="744" extended-state="6" /> <frame x="-8" y="-8" width="1382" height="744" extended-state="6" />
<editor active="true" /> <editor active="false" />
<layout> <layout>
<window_info id="Palette&#9;" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Palette&#9;" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Designer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Designer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3270869" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3270869" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" /> <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32879046" sideWeight="0.5121029" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" /> <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" /> <window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
<window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" /> <window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32879046" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32879046" sideWeight="0.48789713" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Android" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Android" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32879046" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" /> <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32879046" sideWeight="0.4969743" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" /> <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" /> <window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Application Servers" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" /> <window_info id="Application Servers" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.24886535" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" /> <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.24886535" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" /> <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" /> <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24962178" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" /> <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" /> <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" /> <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" /> <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
</layout> </layout>
@ -2079,25 +2010,17 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/app/build.gradle">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="11" column="16" selection-start-line="11" selection-start-column="16" selection-end-line="11" selection-end-column="16" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/InputLanguageSelection.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/InputLanguageSelection.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="92" column="16" selection-start-line="92" selection-start-column="16" selection-end-line="92" selection-end-column="16" /> <caret line="92" column="16" selection-start-line="92" selection-start-column="16" selection-end-line="92" selection-end-column="16" />
<folding> <folding>
<element signature="e#0#5655#0" expanded="true" /> <element signature="e#0#5655#0" expanded="false" />
<element signature="imports" expanded="true" /> <element signature="imports" expanded="false" />
<element signature="e#1509#1539#0" expanded="true" /> <element signature="e#1509#1539#0" expanded="false" />
<element signature="e#2941#2964#0" expanded="true" /> <element signature="e#2941#2964#0" expanded="false" />
<element signature="e#4545#4546#0" expanded="true" /> <element signature="e#4545#4546#0" expanded="false" />
<element signature="e#4577#4578#0" expanded="true" /> <element signature="e#4577#4578#0" expanded="false" />
</folding> </folding>
</state> </state>
</provider> </provider>
@ -2118,14 +2041,6 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/app/src/main/res/values/strings.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-4.88">
<caret line="187" column="34" selection-start-line="187" selection-start-column="18" selection-end-line="187" selection-end-column="34" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardView.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardView.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
@ -2139,8 +2054,8 @@
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="397" column="24" selection-start-line="397" selection-start-column="24" selection-end-line="397" selection-end-column="24" /> <caret line="397" column="24" selection-start-line="397" selection-start-column="24" selection-end-line="397" selection-end-column="24" />
<folding> <folding>
<element signature="e#15971#15972#0" expanded="true" /> <element signature="e#15971#15972#0" expanded="false" />
<element signature="e#16007#16008#0" expanded="true" /> <element signature="e#16007#16008#0" expanded="false" />
</folding> </folding>
</state> </state>
</provider> </provider>
@ -2160,15 +2075,15 @@
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="476" column="38" selection-start-line="476" selection-start-column="38" selection-end-line="476" selection-end-column="38" /> <caret line="476" column="38" selection-start-line="476" selection-start-column="38" selection-end-line="476" selection-end-column="38" />
<folding> <folding>
<element signature="e#5702#5728#0" expanded="true" /> <element signature="e#5702#5728#0" expanded="false" />
<element signature="e#6920#6946#0" expanded="true" /> <element signature="e#6920#6946#0" expanded="false" />
<element signature="e#8140#8166#0" expanded="true" /> <element signature="e#8140#8166#0" expanded="false" />
<element signature="e#9357#9383#0" expanded="true" /> <element signature="e#9357#9383#0" expanded="false" />
<element signature="e#10581#10607#0" expanded="true" /> <element signature="e#10581#10607#0" expanded="false" />
<element signature="e#12082#12108#0" expanded="true" /> <element signature="e#12082#12108#0" expanded="false" />
<element signature="e#13602#13628#0" expanded="true" /> <element signature="e#13602#13628#0" expanded="false" />
<element signature="e#15124#15150#0" expanded="true" /> <element signature="e#15124#15150#0" expanded="false" />
<element signature="e#16643#16669#0" expanded="true" /> <element signature="e#16643#16669#0" expanded="false" />
</folding> </folding>
</state> </state>
</provider> </provider>
@ -2178,7 +2093,7 @@
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="146" column="46" selection-start-line="146" selection-start-column="35" selection-end-line="146" selection-end-column="46" /> <caret line="146" column="46" selection-start-line="146" selection-start-column="35" selection-end-line="146" selection-end-column="46" />
<folding> <folding>
<element signature="e#5666#5692#0" expanded="true" /> <element signature="e#5666#5692#0" expanded="false" />
</folding> </folding>
</state> </state>
</provider> </provider>
@ -2199,6 +2114,16 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/LocaleHelper.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="49" column="53" selection-start-line="49" selection-start-column="53" selection-end-line="49" selection-end-column="53" />
<folding>
<element signature="imports" expanded="false" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinIMESettings.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/LatinIMESettings.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
@ -2207,20 +2132,18 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/LocaleHelper.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/StringForTyping.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="49" column="53" selection-start-line="49" selection-start-column="53" selection-end-line="49" selection-end-column="53" /> <caret line="2" column="13" selection-start-line="2" selection-start-column="13" selection-end-line="2" selection-end-column="13" />
<folding> <folding />
<element signature="imports" expanded="true" />
</folding>
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java"> <entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java">
<provider selected="true" editor-type-id="text-editor"> <provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0"> <state vertical-scroll-proportion="0.0">
<caret line="2465" column="13" selection-start-line="2465" selection-start-column="13" selection-end-line="2465" selection-end-column="13" /> <caret line="2618" column="0" selection-start-line="2618" selection-start-column="0" selection-end-line="2618" selection-end-column="0" />
<folding> <folding>
<element signature="e#17350#17396#0" expanded="true" /> <element signature="e#17350#17396#0" expanded="true" />
<element signature="e#17428#17478#0" expanded="true" /> <element signature="e#17428#17478#0" expanded="true" />
@ -2266,5 +2189,83 @@
</state> </state>
</provider> </provider>
</entry> </entry>
<entry file="file://$PROJECT_DIR$/app/build.gradle">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-4.76">
<caret line="7" column="24" selection-start-line="7" selection-start-column="24" selection-end-line="7" selection-end-column="24" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/kbbridge/KeyboardData.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-12.24">
<caret line="18" column="30" selection-start-line="18" selection-start-column="30" selection-end-line="18" selection-end-column="30" />
<folding>
<element signature="imports" expanded="true" />
<element signature="e#362#363#0" expanded="true" />
<element signature="e#404#405#0" expanded="true" />
<element signature="e#438#439#0" expanded="true" />
<element signature="e#479#480#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/res/xml/accserviceconfig.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="0" column="38" selection-start-line="0" selection-start-column="38" selection-end-line="0" selection-end-column="38" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/res/xml/prefs.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="60" column="46" selection-start-line="60" selection-start-column="46" selection-end-line="60" selection-end-column="46" />
<folding>
<element signature="e#2450#2474#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/res/values/strings.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="-7.56">
<caret line="378" column="0" selection-start-line="378" selection-start-column="0" selection-end-line="378" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/res/values/strings_autofill.xml">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.0">
<caret line="8" column="0" selection-start-line="8" selection-start-column="0" selection-end-line="8" selection-end-column="0" />
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app/src/main/java/keepass2android/autofill/AutoFillService.java">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.7568306">
<caret line="104" column="5" selection-start-line="104" selection-start-column="5" selection-end-line="104" selection-end-column="5" />
<folding>
<element signature="imports" expanded="true" />
<element signature="e#1549#1550#0" expanded="true" />
<element signature="e#1585#1586#0" expanded="true" />
<element signature="e#1660#1661#0" expanded="true" />
<element signature="e#1712#1713#0" expanded="true" />
<element signature="e#2880#2881#0" expanded="true" />
<element signature="e#2913#2914#0" expanded="true" />
<element signature="e#9594#9692#0" expanded="true" />
<element signature="e#9727#9793#0" expanded="true" />
<element signature="e#11813#11814#0" expanded="true" />
<element signature="e#11867#11868#0" expanded="true" />
<element signature="e#11925#11926#0" expanded="true" />
<element signature="e#11979#11980#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component> </component>
</project> </project>

View File

@ -5,7 +5,7 @@ android {
buildToolsVersion "23.0.0" buildToolsVersion "23.0.0"
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 18
targetSdkVersion 23 targetSdkVersion 23
} }

View File

@ -0,0 +1,380 @@
package keepass2android.autofill;
import android.accessibilityservice.AccessibilityService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import keepass2android.kbbridge.KeyboardData;
/**
* Created by Philipp on 25.01.2016.
*/
public class AutoFillService extends AccessibilityService {
private static boolean _hasUsedData = false;
private static String _lastSearchUrl;
private static final String _logTag = "KP2AAF";
private static boolean _isRunning;
private final int autoFillNotificationId = 798810;
private final String androidAppPrefix = "androidapp://";
@Override
public void onCreate() {
super.onCreate();
_isRunning = true;
android.util.Log.d(_logTag, "OnCreate");
}
@Override
public void onDestroy() {
super.onDestroy();
_isRunning = false;
}
interface NodeCondition
{
boolean check(AccessibilityNodeInfo n);
}
class WindowIdCondition implements NodeCondition
{
private int id;
public WindowIdCondition(int id)
{
this.id = id;
}
@Override
public boolean check(AccessibilityNodeInfo n) {
return n.getWindowId() == id;
}
}
class SystemUiCondition implements NodeCondition
{
@Override
public boolean check(AccessibilityNodeInfo n) {
return (n.getViewIdResourceName() != null) && (n.getViewIdResourceName().startsWith("com.android.systemui"));
}
}
private class PasswordFieldCondition implements NodeCondition {
@Override
public boolean check(AccessibilityNodeInfo n) {
return n.isPassword() && (
(n.getText() == null)
|| ("".equals(n.getText())));
}
}
private class EditTextCondition implements NodeCondition {
@Override
public boolean check(AccessibilityNodeInfo n) {
//it seems like n.Editable is not a good check as this is false for some fields which are actually editable, at least in tests with Chrome.
return (n.getClassName() != null) && (n.getClassName().toString().toLowerCase().contains("edittext"));
}
}
public static boolean isAvailable()
{
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
}
public static boolean isRunning()
{
return _isRunning;
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
android.util.Log.d(_logTag, "OnAccEvent");
try
{
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
|| event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
{
android.util.Log.d(_logTag, "event: " + event.getEventType() + ", package = " + event.getPackageName());
if ( "com.android.systemui".equals(event.getPackageName()) )
{
android.util.Log.d(_logTag, "return.");
return; //avoid that the notification is cancelled when pulling down notif drawer
}
else
{
android.util.Log.d(_logTag, "no com.android.systemui");
}
AccessibilityNodeInfo root = getRootInActiveWindow();
int eventWindowId = event.getWindowId();
if ((ExistsNodeOrChildren(root, new WindowIdCondition(eventWindowId)) && !ExistsNodeOrChildren(root, new SystemUiCondition())))
{
boolean cancelNotification = true;
String url = androidAppPrefix + root.getPackageName();
if ( "com.android.chrome".equals(root.getPackageName()) )
{
List<AccessibilityNodeInfo> urlFields = root.findAccessibilityNodeInfosByViewId("com.android.chrome:id/url_bar");
url = urlFromAddressFields(urlFields, url);
}
else if ("com.android.browser".equals(root.getPackageName()))
{
List<AccessibilityNodeInfo> urlFields = root.findAccessibilityNodeInfosByViewId("com.android.browser:id/url");
url = urlFromAddressFields(urlFields, url);
}
if (ExistsNodeOrChildren(root, new PasswordFieldCondition()))
{
if ((getLastReceivedCredentialsUser() != null) &&
(Objects.equals(url, _lastSearchUrl)
|| isSame(getCredentialsField("URL"), url)))
{
android.util.Log.d(_logTag, "Filling credentials for " + url);
List<AccessibilityNodeInfo> emptyPasswordFields = new ArrayList<>();
GetNodeOrChildren(root, new PasswordFieldCondition(), emptyPasswordFields);
List<AccessibilityNodeInfo> allEditTexts = new ArrayList<>();
GetNodeOrChildren(root, new EditTextCondition(), allEditTexts);
AccessibilityNodeInfo usernameEdit = null;
for (int i=0;i<allEditTexts.size();i++)
{
if (allEditTexts.get(i).isPassword() == false)
{
usernameEdit = allEditTexts.get(i);
android.util.Log.d(_logTag, "setting usernameEdit = " + usernameEdit.getText() + " ");
}
else break;
}
FillPassword(url, usernameEdit, emptyPasswordFields);
}
else
{
android.util.Log.d (_logTag, "Notif for " + url );
if (getLastReceivedCredentialsUser() != null)
{
android.util.Log.d (_logTag, getCredentialsField("URL"));
android.util.Log.d (_logTag, url);
}
AskFillPassword(url);
cancelNotification = false;
}
}
if (cancelNotification)
{
((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).cancel(autoFillNotificationId);
android.util.Log.d (_logTag,"Cancel notif");
}
}
}
}
catch (Exception e)
{
android.util.Log.e(_logTag, e.toString());
Notification.Builder builder = new Notification.Builder(this);
//TODO remove on release
builder.setSmallIcon(keepass2android.softkeyboard.R.drawable.ic_notify_autofill)
.setContentText(e.toString())
.setContentTitle("error information")
.setWhen(java.lang.System.currentTimeMillis());
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(autoFillNotificationId+1, builder.build());
}
}
private void AskFillPassword(String url)
{
Intent startKp2aIntent = getPackageManager().getLaunchIntentForPackage(getApplicationContext().getPackageName());
if (startKp2aIntent != null)
{
startKp2aIntent.addCategory(Intent.CATEGORY_LAUNCHER);
startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
String taskName = "SearchUrlTask";
startKp2aIntent.putExtra("KP2A_APPTASK", taskName);
startKp2aIntent.putExtra("UrlToSearch", url);
}
PendingIntent pending = PendingIntent.getActivity(this, 0, startKp2aIntent, PendingIntent.FLAG_UPDATE_CURRENT);
String targetName = url;
if (url.startsWith(androidAppPrefix))
{
String packageName = url.substring(androidAppPrefix.length());
try
{
ApplicationInfo appInfo = getPackageManager().getApplicationInfo(packageName, 0);
targetName = (String) (appInfo != null ? getPackageManager().getApplicationLabel(appInfo) : packageName);
}
catch (Exception e)
{
android.util.Log.d(_logTag, e.toString());
targetName = packageName;
}
}
else
{
targetName = getHost(url);
}
Notification.Builder builder = new Notification.Builder(this);
//TODO icon
//TODO plugin icon
builder.setSmallIcon(keepass2android.softkeyboard.R.drawable.ic_notify_autofill)
.setContentText(getString(keepass2android.softkeyboard.R.string.NotificationContentText, new Object[]{targetName}))
.setContentTitle(getString(keepass2android.softkeyboard.R.string.NotificationTitle))
.setWhen(java.lang.System.currentTimeMillis())
.setVisibility(Notification.VISIBILITY_SECRET)
.setContentIntent(pending);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(autoFillNotificationId, builder.build());
}
private void FillPassword(String url, AccessibilityNodeInfo usernameEdit, List<AccessibilityNodeInfo> passwordFields)
{
if ((keepass2android.kbbridge.KeyboardData.hasData()) && (_hasUsedData == false))
{
fillDataInTextField(usernameEdit, getLastReceivedCredentialsUser());
for (int i=0;i<passwordFields.size();i++)
{
fillDataInTextField(passwordFields.get(i), getLastReceivedCredentialsPassword());
}
_hasUsedData = true;
}
//LookupCredentialsActivity.LastReceivedCredentials = null;
}
private void fillDataInTextField(AccessibilityNodeInfo edit, String value) {
if (value == null)
return;
Bundle b = new Bundle();
b.putString(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, value);
edit.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, b);
}
private boolean isSame(String url1, String url2) {
if (url1.startsWith("androidapp://"))
return url1.equals(url2);
if (url1 == null)
return (url2 == null);
return getHost(url1).equals(getHost(url2));
}
private String getHost(String url)
{
URI uri = null;
try {
uri = new URI(url);
String domain = uri.getHost();
return domain.startsWith("www.") ? domain.substring(4) : domain;
} catch (URISyntaxException e) {
android.util.Log.d(_logTag, "error parsing url: "+ url + e.toString());
return url;
}
}
private String getLastReceivedCredentialsUser() {
return getCredentialsField("UserName");
}
private String getLastReceivedCredentialsPassword() {
return getCredentialsField("Password");
}
private String getCredentialsField(String key) {
for (int i=0;i<KeyboardData.availableFields.size();i++)
{
if (key.equals(KeyboardData.availableFields.get(i).key))
{
if (KeyboardData.availableFields.get(i).value != null)
return KeyboardData.availableFields.get(i).value;
}
}
return null;
}
private void GetNodeOrChildren(AccessibilityNodeInfo n, NodeCondition condition, List<AccessibilityNodeInfo> result) {
if (n != null)
{
if (condition.check(n))
result.add(n);
for (int i = 0; i < n.getChildCount(); i++)
{
GetNodeOrChildren(n.getChild(i), condition, result);
}
}
}
private boolean ExistsNodeOrChildren(AccessibilityNodeInfo n, NodeCondition condition) {
if (n == null) return false;
if (condition.check(n))
return true;
for (int i = 0; i < n.getChildCount(); i++)
{
if (ExistsNodeOrChildren(n.getChild(i), condition))
return true;
}
return false;
}
private String urlFromAddressFields(List<AccessibilityNodeInfo> urlFields, String url) {
if (!urlFields.isEmpty())
{
AccessibilityNodeInfo addressField = urlFields.get(0);
url = addressField.getText().toString();
if (!url.contains("://"))
url = "http://" + url;
}
return url;
}
@Override
public void onInterrupt() {
}
public static void NotifyNewData(String searchUrl)
{
_hasUsedData = false;
_lastSearchUrl = searchUrl;
android.util.Log.d(_logTag, "Notify new data: " + searchUrl);
}
}

View File

@ -16,6 +16,11 @@ public class KeyboardData
return !TextUtils.isEmpty(entryId); return !TextUtils.isEmpty(entryId);
} }
public static boolean bla2()
{
return !TextUtils.isEmpty(entryId);
}
public static void clear() public static void clear()
{ {
availableFields.clear(); availableFields.clear();

View File

@ -376,4 +376,6 @@
<!-- Title for Latin keyboard debug settings activity / dialog --> <!-- Title for Latin keyboard debug settings activity / dialog -->
<string name="english_ime_debug_settings" translatable="false">Android keyboard Debug settings</string> <string name="english_ime_debug_settings" translatable="false">Android keyboard Debug settings</string>
<string name="prefs_debug_mode" translatable="false">Debug Mode</string> <string name="prefs_debug_mode" translatable="false">Debug Mode</string>
</resources> </resources>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="AutoFillServiceDescription">Monitors apps and websites for password fields. Offers to look up credentials from Keepass2Android and auto-fill them into the forms.</string>
<string name="LookupTitle">Look up credentials</string>
<string name="ApplicationName">KP2A AutoFillPlugin</string>
<string name="NotificationTitle">Keepass2Android AutoFill</string>
<string name="NotificationContentText">AutoFill form for %1$s</string>
</resources>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/AutoFillServiceDescription" android:description="@string/AutoFillServiceDescription"
android:accessibilityEventTypes="typeAllMask" android:accessibilityEventTypes="typeAllMask"
@ -7,4 +7,4 @@
android:notificationTimeout="100" android:notificationTimeout="100"
android:canRetrieveWindowContent="true" android:canRetrieveWindowContent="true"
/> />

View File

@ -12,14 +12,14 @@ using Android.Views.Accessibility;
using Android.Widget; using Android.Widget;
using KeePassLib; using KeePassLib;
/*
namespace keepass2android.AutoFill namespace keepass2android.AutoFill
{ {
//<meta-data android:name="android.accessibilityservice" android:resource="@xml/serviceconfig" /> //<meta-data android:name="android.accessibilityservice" android:resource="@xml/serviceconfig" />
[Service(Enabled =true, Permission= "android.permission.BIND_ACCESSIBILITY_SERVICE")] [Service(Enabled =true, Permission= "android.permission.BIND_ACCESSIBILITY_SERVICE")]
[IntentFilter(new[] { "android.accessibilityservice.AccessibilityService" })] [IntentFilter(new[] { "android.accessibilityservice.AccessibilityService" })]
[MetaData("android.accessibilityservice", Resource = "@xml/accserviceconfig")] [MetaData("android.accessibilityservice", Resource = "@xml/accserviceconfig")]
public class Kp2aAccessibilityService : Android.AccessibilityServices.AccessibilityService public class AccessibilityService : Android.AccessibilityServices.AccessibilityService
{ {
private static bool _hasUsedData; private static bool _hasUsedData;
const string _logTag = "KP2AAS"; const string _logTag = "KP2AAS";
@ -53,12 +53,6 @@ namespace keepass2android.AutoFill
{ {
bool cancelNotification = true; bool cancelNotification = true;
var allEditTexts = GetNodeOrChildren(root, IsEditText);
var usernameEdit = allEditTexts.TakeWhile(edit => (edit.Password == false)).LastOrDefault();
string searchString = androidAppPrefix + root.PackageName;
string url = androidAppPrefix + root.PackageName; string url = androidAppPrefix + root.PackageName;
if (root.PackageName == "com.android.chrome") if (root.PackageName == "com.android.chrome")
@ -73,14 +67,24 @@ namespace keepass2android.AutoFill
UrlFromAddressField(ref url, addressField); UrlFromAddressField(ref url, addressField);
} }
List<AccessibilityNodeInfo> emptyPasswordFields = GetNodeOrChildren(root, IsPasswordField); if (ExistsNodeOrChildren(root, IsPasswordField))
if (emptyPasswordFields.Any())
{ {
if ((LastReceivedCredentialsUser != null) && IsSame(GetCredentialsField(PwDefs.UrlField), url)) if ((LastReceivedCredentialsUser != null) && IsSame(GetCredentialsField(PwDefs.UrlField), url))
{ {
Android.Util.Log.Debug ("KP2AAS", "Filling credentials for " + url); Android.Util.Log.Debug ("KP2AAS", "Filling credentials for " + url);
List<AccessibilityNodeInfo> emptyPasswordFields = new List<AccessibilityNodeInfo>();
GetNodeOrChildren(root, IsPasswordField, ref emptyPasswordFields);
List<AccessibilityNodeInfo> allEditTexts = new List<AccessibilityNodeInfo>();
GetNodeOrChildren(root, IsEditText, ref allEditTexts);
var usernameEdit = allEditTexts.TakeWhile(edit => (edit.Password == false)).LastOrDefault();
FillPassword(url, usernameEdit, emptyPasswordFields); FillPassword(url, usernameEdit, emptyPasswordFields);
allEditTexts.Clear();
emptyPasswordFields.Clear();
} }
else else
{ {
@ -91,7 +95,7 @@ namespace keepass2android.AutoFill
Android.Util.Log.Debug ("KP2AAS", url); Android.Util.Log.Debug ("KP2AAS", url);
} }
AskFillPassword(url, usernameEdit, emptyPasswordFields); AskFillPassword(url);
cancelNotification = false; cancelNotification = false;
} }
@ -105,10 +109,11 @@ namespace keepass2android.AutoFill
} }
GC.Collect(); GC.Collect();
Java.Lang.JavaSystem.Gc();
} }
private bool IsSystemUi(AccessibilityNodeInfo n) private bool IsSystemUi(AccessibilityNodeInfo n)
{ {
return (n.ViewIdResourceName != null) && (n.ViewIdResourceName.StartsWith("com.android.systemui")); return (n.ViewIdResourceName != null) && (n.ViewIdResourceName.StartsWith("com.android.systemui"));
@ -146,7 +151,12 @@ namespace keepass2android.AutoFill
return (n.ClassName != null) && (n.ClassName.Contains("EditText")); return (n.ClassName != null) && (n.ClassName.Contains("EditText"));
} }
private void AskFillPassword(string url, AccessibilityNodeInfo usernameEdit, List<AccessibilityNodeInfo> passwordFields) private static bool IsNonPasswordEditText(AccessibilityNodeInfo n)
{
return IsEditText(n) && n.Password == false;
}
private void AskFillPassword(string url)
{ {
Intent startKp2aIntent = PackageManager.GetLaunchIntentForPackage(ApplicationContext.PackageName); Intent startKp2aIntent = PackageManager.GetLaunchIntentForPackage(ApplicationContext.PackageName);
@ -243,6 +253,7 @@ namespace keepass2android.AutoFill
private bool ExistsNodeOrChildren(AccessibilityNodeInfo n, Func<AccessibilityNodeInfo, bool> p) private bool ExistsNodeOrChildren(AccessibilityNodeInfo n, Func<AccessibilityNodeInfo, bool> p)
{ {
if (n == null) return false;
if (p(n)) if (p(n))
return true; return true;
for (int i = 0; i < n.ChildCount; i++) for (int i = 0; i < n.ChildCount; i++)
@ -253,19 +264,17 @@ namespace keepass2android.AutoFill
return false; return false;
} }
private List<AccessibilityNodeInfo> GetNodeOrChildren(AccessibilityNodeInfo n, Func<AccessibilityNodeInfo, bool> p) private void GetNodeOrChildren(AccessibilityNodeInfo n, Func<AccessibilityNodeInfo, bool> p, ref List<AccessibilityNodeInfo> result)
{ {
List<AccessibilityNodeInfo> result = new List<AccessibilityNodeInfo>();
if (n != null) if (n != null)
{ {
if (p(n)) if (p(n))
result.Add(n); result.Add(n);
for (int i = 0; i < n.ChildCount; i++) for (int i = 0; i < n.ChildCount; i++)
{ {
result.AddRange(GetNodeOrChildren(n.GetChild(i), p)); GetNodeOrChildren(n.GetChild(i), p, ref result);
} }
} }
return result;
} }
public override void OnInterrupt() public override void OnInterrupt()
@ -283,4 +292,4 @@ namespace keepass2android.AutoFill
_hasUsedData = false; _hasUsedData = false;
} }
} }
} }*/

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Preferences;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace keepass2android
{
[Activity(Label = AppNames.AppName, Theme = "@style/MyTheme_ActionBar")]
public class ActivateAutoFillActivity : LifecycleDebugActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
new ActivityDesign(this).ApplyTheme();
base.OnCreate(savedInstanceState);
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
App.Kp2a.AskYesNoCancel(UiStringKey.ActivateAutoFillService_title,
UiStringKey.ActivateAutoFillService_message,
UiStringKey.ActivateAutoFillService_btnKeyboard,
UiStringKey.ActivateAutoFillService_btnAutoFill,
delegate
{
//yes
CopyToClipboardService.ActivateKeyboard(this);
Finish();
},
delegate
{
//no
Intent intent = new Intent(Android.Provider.Settings.ActionAccessibilitySettings);
StartActivity(intent);
prefs.Edit().PutBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), false).Commit();
Toast.MakeText(this, Resource.String.ActivateAutoFillService_toast, ToastLength.Long).Show();
Finish();
},
delegate
{
//cancel
Finish();
},
(sender, args) => Finish() //dismiss
,this);
}
}
}

View File

@ -409,7 +409,7 @@ namespace keepass2android
Intent showNotIntent = new Intent(this, typeof (CopyToClipboardService)); Intent showNotIntent = new Intent(this, typeof (CopyToClipboardService));
showNotIntent.SetAction(Intents.ShowNotification); showNotIntent.SetAction(Intents.ShowNotification);
showNotIntent.PutExtra(KeyEntry, Entry.Uuid.ToHexString()); showNotIntent.PutExtra(KeyEntry, Entry.Uuid.ToHexString());
_appTask.PopulatePasswordAccessServiceIntent(showNotIntent);
showNotIntent.PutExtra(KeyCloseAfterCreate, closeAfterCreate); showNotIntent.PutExtra(KeyCloseAfterCreate, closeAfterCreate);
StartService(showNotIntent); StartService(showNotIntent);

View File

@ -54,6 +54,13 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name="keepass2android.autofill.AutoFillService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
<activity android:configChanges="orientation" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" android:windowSoftInputMode="adjustResize"> <activity android:configChanges="orientation" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.PasswordActivity" android:windowSoftInputMode="adjustResize">
<intent-filter android:label="@string/app_name"> <intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
@ -101,4 +108,6 @@
<uses-permission android:name="android.permission.USE_FINGERPRINT" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" />
<!-- Samsung Pass permission --> <!-- Samsung Pass permission -->
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" /> <uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
</manifest> </manifest>

View File

@ -33,6 +33,13 @@
<category android:name="android.intent.category.OPENABLE" /> <category android:name="android.intent.category.OPENABLE" />
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name="keepass2android.autofill.AutoFillService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD"> <service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter> <intent-filter>
<action android:name="android.view.InputMethod" /> <action android:name="android.view.InputMethod" />
@ -102,6 +109,8 @@
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" /> <uses-permission android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<!-- Samsung Pass permission --> <!-- Samsung Pass permission -->
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" /> <uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
</manifest> </manifest>

View File

@ -16,6 +16,12 @@
<category android:name="android.intent.category.OPENABLE" /> <category android:name="android.intent.category.OPENABLE" />
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name="keepass2android.autofill.AutoFillService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD"> <service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD">
<intent-filter> <intent-filter>
<action android:name="android.view.InputMethod" /> <action android:name="android.view.InputMethod" />

View File

@ -354,7 +354,7 @@
<string name="ShowSeparateNotifications_summary">Show separate notifications for copying username and password to clipboard and activating the keyboard.</string> <string name="ShowSeparateNotifications_summary">Show separate notifications for copying username and password to clipboard and activating the keyboard.</string>
<string name="ShowKp2aKeyboardNotification_title">KP2A keyboard notification</string> <string name="ShowKp2aKeyboardNotification_title">KP2A keyboard notification</string>
<string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string> <string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard and AutoFill service (recommended).</string>
<string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string> <string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string>
<string name="OpenKp2aKeyboardAutomatically_summary">Open keyboard selection dialog when entry is available through KP2A keyboard after search from the browser.</string> <string name="OpenKp2aKeyboardAutomatically_summary">Open keyboard selection dialog when entry is available through KP2A keyboard after search from the browser.</string>
@ -647,11 +647,11 @@
<string name="ErrorReportAsk">Ask after error</string> <string name="ErrorReportAsk">Ask after error</string>
<string name="ErrorReportPrefTitle">Send error reports</string> <string name="ErrorReportPrefTitle">Send error reports</string>
<string name="LookupTitle">Look up credentials</string> <string name="ActivateAutoFillService_title">Activate AutoFill?</string>
<string name="ApplicationName">KP2A AutoFillPlugin</string> <string name="ActivateAutoFillService_message">Credentials can be transferred to other apps in several ways: You can copy values to clipboard, but please note that the clipboard is not secure in Android. The built-in keyboard gives full access to the selected entry but must be enabled each time you want to access the credentials. On Android 5 and later, Keepass2Android can enter username and password automatically using the AutoFill service.</string>
<string name="AutoFillServiceDescription">Monitors apps and websites for password fields. Offers to look up credentials from Keepass2Android and auto-fill them into the forms.</string> <string name="ActivateAutoFillService_btnKeyboard">Use built-in keyboard</string>
<string name="NotificationTitle">Keepass2Android AutoFill</string> <string name="ActivateAutoFillService_btnAutoFill">Use AutoFill service</string>
<string name="NotificationContentText">AutoFill form for %1$s</string> <string name="ActivateAutoFillService_toast">Please enable the Keepass2Android service.</string>
<string name="ChangeLog_0_9_8c"> <string name="ChangeLog_0_9_8c">
Version 0.9.8c\n Version 0.9.8c\n

View File

@ -347,7 +347,7 @@ namespace keepass2android
#endif #endif
} }
class DismissListener: Java.Lang.Object, IDialogInterfaceOnDismissListener public class DismissListener: Java.Lang.Object, IDialogInterfaceOnDismissListener
{ {
private readonly Action _onDismiss; private readonly Action _onDismiss;

View File

@ -328,6 +328,17 @@ namespace keepass2android
EventHandler<DialogClickEventArgs> noHandler, EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler, EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx) Context ctx)
{
AskYesNoCancel(titleKey, messageKey, yesString, noString, yesHandler, noHandler, cancelHandler, null, ctx);
}
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
UiStringKey yesString, UiStringKey noString,
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
EventHandler dismissHandler,
Context ctx)
{ {
Handler handler = new Handler(Looper.MainLooper); Handler handler = new Handler(Looper.MainLooper);
handler.Post(() => handler.Post(() =>
@ -353,7 +364,11 @@ namespace keepass2android
cancelHandler); cancelHandler);
} }
AlertDialog dialog = builder.Create(); AlertDialog dialog = builder.Create();
if (dismissHandler != null)
dialog.SetOnDismissListener(new Util.DismissListener(() => dismissHandler(dialog, EventArgs.Empty)));
dialog.Show(); dialog.Show();
if (yesText.Length + noText.Length + cancelText.Length >= 20) if (yesText.Length + noText.Length + cancelText.Length >= 20)

View File

@ -327,6 +327,11 @@ namespace keepass2android
{ {
activity.StartNotificationsService(false); activity.StartNotificationsService(false);
} }
virtual public void PopulatePasswordAccessServiceIntent(Intent intent)
{
}
} }
/// <summary> /// <summary>
@ -393,7 +398,11 @@ namespace keepass2android
//act.AppTask = new NullTask(); //act.AppTask = new NullTask();
} }
public override void PopulatePasswordAccessServiceIntent(Intent intent)
{
base.PopulatePasswordAccessServiceIntent(intent);
intent.PutExtra(UrlToSearchKey, UrlToSearchFor);
}
} }

View File

@ -116,6 +116,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ActivateAutoFillActivity.cs" />
<Compile Include="addons\OtpKeyProv\EncodingUtil.cs" /> <Compile Include="addons\OtpKeyProv\EncodingUtil.cs" />
<Compile Include="addons\OtpKeyProv\OathHotpKeyProv.cs" /> <Compile Include="addons\OtpKeyProv\OathHotpKeyProv.cs" />
<Compile Include="addons\OtpKeyProv\OtpAuxCachingFileStorage.cs" /> <Compile Include="addons\OtpKeyProv\OtpAuxCachingFileStorage.cs" />
@ -155,7 +156,7 @@
<Compile Include="icons\DrawableFactory.cs" /> <Compile Include="icons\DrawableFactory.cs" />
<Compile Include="KeeChallenge.cs" /> <Compile Include="KeeChallenge.cs" />
<Compile Include="FixedDrawerLayout.cs" /> <Compile Include="FixedDrawerLayout.cs" />
<Compile Include="Kp2aAccessibilityService.cs" /> <Compile Include="AccessibilityService.cs" />
<Compile Include="KpEntryTemplatedEdit.cs" /> <Compile Include="KpEntryTemplatedEdit.cs" />
<Compile Include="MeasuringRelativeLayout.cs" /> <Compile Include="MeasuringRelativeLayout.cs" />
<Compile Include="NfcOtpActivity.cs" /> <Compile Include="NfcOtpActivity.cs" />
@ -1671,14 +1672,6 @@
<ItemGroup> <ItemGroup>
<AndroidResource Include="Resources\drawable-mdpi\ic_fp_40px.png" /> <AndroidResource Include="Resources\drawable-mdpi\ic_fp_40px.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable-xhdpi\ic_notify_autofill.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\xml\accserviceconfig.xml">
<SubType>Designer</SubType>
</AndroidResource>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets')" /> <Import Project="..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.11.3\build\MonoAndroid10\Xamarin.Insights.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View File

@ -18,6 +18,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Android.AccessibilityServices;
using Android.Support.V4.App; using Android.Support.V4.App;
using Java.Util; using Java.Util;
@ -27,10 +28,10 @@ using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Widget; using Android.Widget;
using Android.Preferences; using Android.Preferences;
using Android.Views.Accessibility;
using KeePassLib; using KeePassLib;
using KeePassLib.Utility; using KeePassLib.Utility;
using Android.Views.InputMethods; using Android.Views.InputMethods;
using keepass2android.AutoFill;
using KeePass.Util.Spr; using KeePass.Util.Spr;
namespace keepass2android namespace keepass2android
@ -278,6 +279,7 @@ namespace keepass2android
if ((intent.Action == Intents.ShowNotification) || (intent.Action == Intents.UpdateKeyboard)) if ((intent.Action == Intents.ShowNotification) || (intent.Action == Intents.UpdateKeyboard))
{ {
String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry); String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry);
String searchUrl = intent.GetStringExtra(SearchUrlTask.UrlToSearchKey);
PwUuid entryId = PwUuid.Zero; PwUuid entryId = PwUuid.Zero;
if (uuidBytes != null) if (uuidBytes != null)
@ -308,7 +310,7 @@ namespace keepass2android
{ {
//first time opening the entry -> bring up the notifications //first time opening the entry -> bring up the notifications
bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KeyCloseAfterCreate, false); bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KeyCloseAfterCreate, false);
DisplayAccessNotifications(entry, closeAfterCreate); DisplayAccessNotifications(entry, closeAfterCreate, searchUrl);
} }
else //UpdateKeyboard else //UpdateKeyboard
{ {
@ -317,7 +319,7 @@ namespace keepass2android
//update the keyboard data. //update the keyboard data.
//Check if keyboard is (still) available //Check if keyboard is (still) available
if (Keepass2android.Kbbridge.KeyboardData.EntryId == entry.Uuid.ToHexString()) if (Keepass2android.Kbbridge.KeyboardData.EntryId == entry.Uuid.ToHexString())
MakeAccessibleForKeyboard(entry); MakeAccessibleForKeyboard(entry, searchUrl);
#endif #endif
} }
} }
@ -386,7 +388,7 @@ namespace keepass2android
private const string ActionNotificationCancelled = "notification_cancelled"; private const string ActionNotificationCancelled = "notification_cancelled";
public void DisplayAccessNotifications(PwEntryOutput entry, bool closeAfterCreate) public void DisplayAccessNotifications(PwEntryOutput entry, bool closeAfterCreate, string searchUrl)
{ {
var hadKeyboardData = ClearNotifications(); var hadKeyboardData = ClearNotifications();
@ -414,28 +416,22 @@ namespace keepass2android
{ {
//keyboard //keyboard
hasKeyboardDataNow = MakeAccessibleForKeyboard(entry); hasKeyboardDataNow = MakeAccessibleForKeyboard(entry, searchUrl);
if (hasKeyboardDataNow) if (hasKeyboardDataNow)
{ {
notBuilder.AddKeyboardAccess(); notBuilder.AddKeyboardAccess();
if (prefs.GetBoolean("kp2a_switch_rooted", false))
if (Keepass2android.Autofill.AutoFillService.IsAvailable && (!Keepass2android.Autofill.AutoFillService.IsRunning))
{ {
//switch rooted if (!prefs.GetBoolean("has_asked_autofillservice", false))
bool onlySwitchOnSearch = prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
if (closeAfterCreate || (!onlySwitchOnSearch))
{ {
ActivateKp2aKeyboard(); var i = new Intent(this, typeof (ActivateAutoFillActivity));
} i.AddFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
} StartActivity(i);
else prefs.Edit().PutBoolean("has_asked_autofillservice", true).Commit();
{
//if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
// automatically bring up the Keyboard selection dialog
if ((closeAfterCreate) && prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
{
ActivateKp2aKeyboard();
} }
} }
else ActivateKeyboardIfAppropriate(closeAfterCreate, prefs);
} }
@ -465,6 +461,31 @@ namespace keepass2android
RegisterReceiver(_notificationDeletedBroadcastReceiver, deletefilter); RegisterReceiver(_notificationDeletedBroadcastReceiver, deletefilter);
} }
public void ActivateKeyboardIfAppropriate(bool closeAfterCreate, ISharedPreferences prefs)
{
if (prefs.GetBoolean("kp2a_switch_rooted", false))
{
//switch rooted
bool onlySwitchOnSearch = prefs.GetBoolean(
GetString(Resource.String.OpenKp2aKeyboardAutomaticallyOnlyAfterSearch_key), false);
if (closeAfterCreate || (!onlySwitchOnSearch))
{
ActivateKp2aKeyboard();
}
}
else
{
//if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
// automatically bring up the Keyboard selection dialog
if ((closeAfterCreate) &&
prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key),
Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
{
ActivateKp2aKeyboard();
}
}
}
private bool ClearNotifications() private bool ClearNotifications()
{ {
// Notification Manager // Notification Manager
@ -479,7 +500,7 @@ namespace keepass2android
return hadKeyboardData; return hadKeyboardData;
} }
bool MakeAccessibleForKeyboard(PwEntryOutput entry) bool MakeAccessibleForKeyboard(PwEntryOutput entry, string searchUrl)
{ {
#if EXCLUDE_KEYBOARD #if EXCLUDE_KEYBOARD
return false; return false;
@ -529,7 +550,7 @@ namespace keepass2android
Keepass2android.Kbbridge.KeyboardData.EntryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField); Keepass2android.Kbbridge.KeyboardData.EntryName = entry.OutputStrings.ReadSafe(PwDefs.TitleField);
Keepass2android.Kbbridge.KeyboardData.EntryId = entry.Uuid.ToHexString(); Keepass2android.Kbbridge.KeyboardData.EntryId = entry.Uuid.ToHexString();
if (hasData) if (hasData)
Kp2aAccessibilityService.NotifyNewData(); Keepass2android.Autofill.AutoFillService.NotifyNewData(searchUrl);
return hasData; return hasData;
#endif #endif