updates to sample plugin and PluginSDK
This commit is contained in:
@@ -2,6 +2,7 @@ package keepass2android.pluginsdk;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
@@ -71,5 +72,40 @@ public class Kp2aControl {
|
|||||||
i.putExtra(Strings.EXTRA_QUERY_STRING, searchText);
|
i.putExtra(Strings.EXTRA_QUERY_STRING, searchText);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an intent to query a password entry from KP2A, matching to the current app's package .
|
||||||
|
* The credentials are returned as Activity result.
|
||||||
|
* This requires SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE.
|
||||||
|
* @return an Intent to start KP2A with
|
||||||
|
*/
|
||||||
|
public static Intent getQueryEntryIntentForOwnPackage()
|
||||||
|
{
|
||||||
|
return new Intent(Strings.ACTION_QUERY_CREDENTIALS_FOR_OWN_PACKAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the entry fields returned in an intent from a query to a hashmap.
|
||||||
|
* @param intent data received in onActivityResult after getQueryEntryIntent(ForOwnPackage)
|
||||||
|
* @return HashMap with keys = field names (see KeepassDefs for standard keys) and values = values
|
||||||
|
*/
|
||||||
|
public static HashMap<String, String> getEntryFieldsFromIntent(Intent intent)
|
||||||
|
{
|
||||||
|
HashMap<String, String> res = new HashMap<String, String>();
|
||||||
|
try {
|
||||||
|
JSONObject json = new JSONObject(intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA));
|
||||||
|
for(Iterator<String> iter = json.keys();iter.hasNext();) {
|
||||||
|
String key = iter.next();
|
||||||
|
String value = json.get(key).toString();
|
||||||
|
res.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@
|
|||||||
<action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
|
<action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
|
||||||
<action android:name="keepass2android.ACTION_RECEIVE_ACCESS" />
|
<action android:name="keepass2android.ACTION_RECEIVE_ACCESS" />
|
||||||
<action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
|
<action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
|
||||||
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ public final class R {
|
|||||||
public static final int ic_launcher=0x7f020000;
|
public static final int ic_launcher=0x7f020000;
|
||||||
}
|
}
|
||||||
public static final class id {
|
public static final class id {
|
||||||
public static final int action_settings=0x7f080001;
|
public static final int action_settings=0x7f080003;
|
||||||
|
public static final int btnAdd=0x7f080001;
|
||||||
|
public static final int btnQuery=0x7f080002;
|
||||||
public static final int container=0x7f080000;
|
public static final int container=0x7f080000;
|
||||||
}
|
}
|
||||||
public static final class layout {
|
public static final class layout {
|
||||||
|
|||||||
@@ -8,9 +8,18 @@
|
|||||||
android:paddingTop="@dimen/activity_vertical_margin"
|
android:paddingTop="@dimen/activity_vertical_margin"
|
||||||
tools:context="keepass2android.plugina.PlugInA$PlaceholderFragment" >
|
tools:context="keepass2android.plugina.PlugInA$PlaceholderFragment" >
|
||||||
|
|
||||||
<TextView
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnAdd"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/hello_world" />
|
android:text="add credentials to KP2A"/>
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnQuery"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="query credentials for this package"
|
||||||
|
android:layout_below="@id/btnAdd"
|
||||||
|
/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
package keepass2android.plugina;
|
package keepass2android.plugina;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import keepass2android.pluginsdk.KeepassDefs;
|
||||||
|
import keepass2android.pluginsdk.Kp2aControl;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.View.OnClickListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.os.Build;
|
import android.widget.Toast;
|
||||||
|
|
||||||
public class PlugInA extends Activity {
|
public class PlugInA extends Activity {
|
||||||
|
|
||||||
@@ -47,6 +55,8 @@ public class PlugInA extends Activity {
|
|||||||
*/
|
*/
|
||||||
public static class PlaceholderFragment extends Fragment {
|
public static class PlaceholderFragment extends Fragment {
|
||||||
|
|
||||||
|
private static final String PLUGIN_A_PASSPHRASE = "PluginA passphrase";
|
||||||
|
|
||||||
public PlaceholderFragment() {
|
public PlaceholderFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,8 +65,83 @@ public class PlugInA extends Activity {
|
|||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View rootView = inflater.inflate(R.layout.fragment_plug_in,
|
View rootView = inflater.inflate(R.layout.fragment_plug_in,
|
||||||
container, false);
|
container, false);
|
||||||
|
|
||||||
|
rootView.findViewById(R.id.btnQuery).setOnClickListener(
|
||||||
|
new OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
try {
|
||||||
|
PlaceholderFragment.this.startActivityForResult(
|
||||||
|
Kp2aControl
|
||||||
|
.getQueryEntryIntentForOwnPackage(),
|
||||||
|
1);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Toast.makeText(
|
||||||
|
PlaceholderFragment.this.getActivity(),
|
||||||
|
"no KP2A host app found",
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
rootView.findViewById(R.id.btnAdd).setOnClickListener(
|
||||||
|
new OnClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
HashMap<String, String> fields = new HashMap<String, String>();
|
||||||
|
//standard fields
|
||||||
|
fields.put(KeepassDefs.TitleField, "plugin A");
|
||||||
|
fields.put(KeepassDefs.UserNameField, "John Doe");
|
||||||
|
fields.put(KeepassDefs.PasswordField, "top secret");
|
||||||
|
//associate entry with our app. If we would require the URL field for a web URL,
|
||||||
|
//this string could be added in any other (e.g. a custom) field
|
||||||
|
fields.put(KeepassDefs.UrlField, "androidapp://"+getActivity().getPackageName());
|
||||||
|
//custom field:
|
||||||
|
fields.put(PLUGIN_A_PASSPHRASE, "some long text");
|
||||||
|
//mark custom field as protected (i.e. display masked, enable memory protection in Keepass2)
|
||||||
|
ArrayList<String> protectedFields = new ArrayList<String>();
|
||||||
|
protectedFields.add(PLUGIN_A_PASSPHRASE);
|
||||||
|
|
||||||
|
//add to KP2A
|
||||||
|
PlaceholderFragment.this.startActivityForResult(
|
||||||
|
Kp2aControl
|
||||||
|
.getAddEntryIntent(fields, protectedFields),
|
||||||
|
2);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Toast.makeText(
|
||||||
|
PlaceholderFragment.this.getActivity(),
|
||||||
|
"no KP2A host app found",
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int requestCode, int resultCode,
|
||||||
|
Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
||||||
|
if ((requestCode == 1) //queryEntry for own package
|
||||||
|
&& (resultCode == RESULT_OK)) // ensure user granted access and selected something
|
||||||
|
{
|
||||||
|
HashMap<String, String> credentials = Kp2aControl.getEntryFieldsFromIntent(data);
|
||||||
|
if (!credentials.isEmpty())
|
||||||
|
{
|
||||||
|
//here we go!
|
||||||
|
Toast.makeText(getActivity(), "retrieved credenitals! Username="+credentials.get(KeepassDefs.UserNameField), Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public class PluginAAccessReceiver
|
|||||||
ArrayList<String> scopes = new ArrayList<String>();
|
ArrayList<String> scopes = new ArrayList<String>();
|
||||||
scopes.add(Strings.SCOPE_DATABASE_ACTIONS);
|
scopes.add(Strings.SCOPE_DATABASE_ACTIONS);
|
||||||
scopes.add(Strings.SCOPE_CURRENT_ENTRY);
|
scopes.add(Strings.SCOPE_CURRENT_ENTRY);
|
||||||
|
scopes.add(Strings.SCOPE_QUERY_CREDENTIALS_FOR_OWN_PACKAGE);
|
||||||
return scopes;
|
return scopes;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="keepass2android.plugin.qr"
|
package="keepass2android.plugin.qr"
|
||||||
android:versionCode="1"
|
android:versionCode="2"
|
||||||
android:versionName="1.0" >
|
android:versionName="1.0.1" >
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.CAMERA"/>
|
<uses-permission android:name="android.permission.CAMERA"/>
|
||||||
<uses-permission
|
<uses-permission
|
||||||
@@ -10,10 +10,10 @@
|
|||||||
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
|
android:permissionGroup="android.permission-group.HARDWARE_CONTROLS"
|
||||||
android:protectionLevel="normal" />
|
android:protectionLevel="normal" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-feature android:name="android.hardware.camera"/>
|
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||||
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
|
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.camera.flash" android:required="false"/>
|
<uses-feature android:name="android.hardware.camera.flash" android:required="false"/>
|
||||||
|
<uses-feature android:name="android.hardware.screen.portrait" android:required="false"/>
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="14"
|
android:minSdkVersion="14"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.json.JSONObject;
|
|||||||
|
|
||||||
import keepass2android.pluginsdk.AccessManager;
|
import keepass2android.pluginsdk.AccessManager;
|
||||||
import keepass2android.pluginsdk.KeepassDefs;
|
import keepass2android.pluginsdk.KeepassDefs;
|
||||||
|
import keepass2android.pluginsdk.Kp2aControl;
|
||||||
import keepass2android.pluginsdk.Strings;
|
import keepass2android.pluginsdk.Strings;
|
||||||
|
|
||||||
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.BarcodeFormat;
|
||||||
@@ -65,8 +66,7 @@ public class QRActivity extends Activity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if ((getIntent() != null) && (getIntent().getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA)!= null))
|
if ((getIntent() != null) && (getIntent().getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA)!= null))
|
||||||
|
setContentView(R.layout.activity_qr);
|
||||||
setContentView(R.layout.activity_qr);
|
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
getFragmentManager().beginTransaction()
|
getFragmentManager().beginTransaction()
|
||||||
@@ -118,24 +118,7 @@ public class QRActivity extends Activity {
|
|||||||
public PlaceholderFragment() {
|
public PlaceholderFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HashMap<String, String> getEntryFieldsFromIntent(Intent intent)
|
|
||||||
{
|
|
||||||
HashMap<String, String> res = new HashMap<String, String>();
|
|
||||||
try {
|
|
||||||
JSONObject json = new JSONObject(intent.getStringExtra(Strings.EXTRA_ENTRY_OUTPUT_DATA));
|
|
||||||
for(Iterator<String> iter = json.keys();iter.hasNext();) {
|
|
||||||
String key = iter.next();
|
|
||||||
String value = json.get(key).toString();
|
|
||||||
res.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (JSONException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
@@ -145,7 +128,7 @@ public class QRActivity extends Activity {
|
|||||||
|
|
||||||
mSpinner = (Spinner) rootView.findViewById(R.id.spinner);
|
mSpinner = (Spinner) rootView.findViewById(R.id.spinner);
|
||||||
|
|
||||||
mEntryOutput = getEntryFieldsFromIntent(getActivity().getIntent());
|
mEntryOutput = Kp2aControl.getEntryFieldsFromIntent(getActivity().getIntent());
|
||||||
mProtectedFieldsList = getProtectedFieldsList(getActivity().getIntent());
|
mProtectedFieldsList = getProtectedFieldsList(getActivity().getIntent());
|
||||||
|
|
||||||
ArrayList<String> spinnerItems = new ArrayList<String>();
|
ArrayList<String> spinnerItems = new ArrayList<String>();
|
||||||
|
|||||||
Reference in New Issue
Block a user