mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
New Notification engine
This commit is contained in:
@@ -39,8 +39,9 @@ import com.keepassdroid.compat.ActivityCompat;
|
||||
import com.keepassdroid.database.Database;
|
||||
import com.keepassdroid.database.PwDatabase;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.password.PasswordActivity;
|
||||
import com.keepassdroid.notifications.NotificationCopyingService;
|
||||
import com.keepassdroid.notifications.NotificationField;
|
||||
import com.keepassdroid.password.PasswordActivity;
|
||||
import com.keepassdroid.settings.PreferencesUtil;
|
||||
import com.keepassdroid.timeout.ClipboardHelper;
|
||||
import com.keepassdroid.utils.EmptyUtils;
|
||||
@@ -50,6 +51,7 @@ import com.keepassdroid.utils.Util;
|
||||
import com.keepassdroid.view.EntryContentsView;
|
||||
import com.kunzisoft.keepass.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@@ -146,12 +148,26 @@ public class EntryActivity extends LockingHideActivity {
|
||||
// username already copied, waiting for user's action before copy password.
|
||||
Intent intent = new Intent(this, NotificationCopyingService.class);
|
||||
intent.setAction(NotificationCopyingService.ACTION_NEW_NOTIFICATION);
|
||||
intent.putExtra(NotificationCopyingService.EXTRA_PASSWORD, mEntry.getPassword());
|
||||
if (mEntry.getUsername().length() > 0) {
|
||||
intent.putExtra(NotificationCopyingService.EXTRA_USERNAME, mEntry.getUsername());
|
||||
}
|
||||
if (mEntry.getTitle() != null)
|
||||
intent.putExtra(NotificationCopyingService.EXTRA_ENTRY_TITLE, mEntry.getTitle());
|
||||
// Construct notification fields
|
||||
ArrayList<NotificationField> notificationFields = new ArrayList<>();
|
||||
// Add username if exists to notifications
|
||||
if (mEntry.getUsername().length() > 0)
|
||||
notificationFields.add(
|
||||
new NotificationField(
|
||||
NotificationField.NotificationFieldId.USERNAME,
|
||||
mEntry.getUsername(),
|
||||
getResources()));
|
||||
// Add password to notifications
|
||||
notificationFields.add(
|
||||
new NotificationField(
|
||||
NotificationField.NotificationFieldId.PASSWORD,
|
||||
mEntry.getPassword(),
|
||||
getResources()));
|
||||
// Add notifications
|
||||
intent.putParcelableArrayListExtra(NotificationCopyingService.EXTRA_FIELDS, notificationFields);
|
||||
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,12 +30,7 @@ public class NotificationCopyingService extends Service {
|
||||
|
||||
public static final String ACTION_NEW_NOTIFICATION = "ACTION_NEW_NOTIFICATION";
|
||||
public static final String EXTRA_ENTRY_TITLE = "EXTRA_ENTRY_TITLE";
|
||||
public static final String EXTRA_USERNAME = "EXTRA_USERNAME";
|
||||
public static final String EXTRA_PASSWORD = "EXTRA_PASSWORD";
|
||||
|
||||
public static final String ACTION_COPY_USERNAME = "ACTION_COPY_USERNAME";
|
||||
public static final String ACTION_COPY_PASSWORD = "ACTION_COPY_PASSWORD";
|
||||
|
||||
public static final String EXTRA_FIELDS = "EXTRA_FIELDS";
|
||||
public static final String ACTION_CLEAN_CLIPBOARD = "ACTION_CLEAN_CLIPBOARD";
|
||||
|
||||
private NotificationManager notificationManager;
|
||||
@@ -81,21 +76,8 @@ public class NotificationCopyingService extends Service {
|
||||
|
||||
} else if (ACTION_NEW_NOTIFICATION.equals(intent.getAction())) {
|
||||
String title = intent.getStringExtra(EXTRA_ENTRY_TITLE);
|
||||
String password = intent.getStringExtra(EXTRA_PASSWORD);
|
||||
if (password == null) {
|
||||
Log.e(TAG, "password is null");
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
newNotification(title, constructListOfField(intent));
|
||||
|
||||
} else if (ACTION_COPY_USERNAME.equals(intent.getAction())) {
|
||||
String fieldValueToCopy = intent.getStringExtra(EXTRA_USERNAME);
|
||||
copyField(new Field(EXTRA_USERNAME, fieldValueToCopy), constructListOfField(intent));
|
||||
|
||||
} else if (ACTION_COPY_PASSWORD.equals(intent.getAction())) {
|
||||
String fieldValueToCopy = intent.getStringExtra(EXTRA_PASSWORD);
|
||||
copyField(new Field(EXTRA_PASSWORD, fieldValueToCopy), constructListOfField(intent));
|
||||
|
||||
} else if (ACTION_CLEAN_CLIPBOARD.equals(intent.getAction())) {
|
||||
stopTask(countingDownTask);
|
||||
try {
|
||||
@@ -103,66 +85,43 @@ public class NotificationCopyingService extends Service {
|
||||
} catch (SamsungClipboardException e) {
|
||||
Log.e(TAG, "Clipboard can't be cleaned", e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.w(TAG, "unknown action");
|
||||
for (String actionKey : NotificationField.getAllActionKeys()) {
|
||||
if (actionKey.equals(intent.getAction())) {
|
||||
NotificationField fieldToCopy = intent.getParcelableExtra(
|
||||
NotificationField.getExtraKeyLinkToActionKey(actionKey));
|
||||
ArrayList<NotificationField> nextFields = constructListOfField(intent);
|
||||
// Remove the current field from the next fields
|
||||
if (nextFields.contains(fieldToCopy))
|
||||
nextFields.remove(fieldToCopy);
|
||||
copyField(fieldToCopy, nextFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
||||
private List<Field> constructListOfField(Intent intent) {
|
||||
List<Field> fieldList = new ArrayList<>();
|
||||
private ArrayList<NotificationField> constructListOfField(Intent intent) {
|
||||
ArrayList<NotificationField> fieldList = new ArrayList<>();
|
||||
if (intent != null && intent.getExtras() != null) {
|
||||
if (intent.getExtras().containsKey(EXTRA_USERNAME))
|
||||
fieldList.add(new Field(
|
||||
EXTRA_USERNAME,
|
||||
intent.getStringExtra(EXTRA_USERNAME)));
|
||||
if (intent.getExtras().containsKey(EXTRA_PASSWORD))
|
||||
fieldList.add(new Field(
|
||||
EXTRA_PASSWORD,
|
||||
intent.getStringExtra(EXTRA_PASSWORD)));
|
||||
if (intent.getExtras().containsKey(EXTRA_FIELDS))
|
||||
fieldList = intent.getParcelableArrayListExtra(EXTRA_FIELDS);
|
||||
}
|
||||
return fieldList;
|
||||
}
|
||||
|
||||
private String getLabelFromExtra(String extra) {
|
||||
switch (extra) {
|
||||
case EXTRA_USERNAME:
|
||||
return getString(R.string.entry_user_name);
|
||||
case EXTRA_PASSWORD:
|
||||
return getString(R.string.entry_password);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String getCopyTextFromExtra(String extra) {
|
||||
switch (extra) {
|
||||
case EXTRA_USERNAME:
|
||||
return getString(R.string.copy_username);
|
||||
case EXTRA_PASSWORD:
|
||||
return getString(R.string.copy_password);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private PendingIntent getCopyPendingIntent(Field field, List<Field> fieldsToAdd) {
|
||||
private PendingIntent getCopyPendingIntent(NotificationField fieldToCopy, ArrayList<NotificationField> fieldsToAdd) {
|
||||
Intent copyIntent = new Intent(this, NotificationCopyingService.class);
|
||||
switch (field.extra) {
|
||||
case EXTRA_USERNAME:
|
||||
copyIntent.setAction(ACTION_COPY_USERNAME);
|
||||
break;
|
||||
case EXTRA_PASSWORD:
|
||||
copyIntent.setAction(ACTION_COPY_PASSWORD);
|
||||
}
|
||||
for (Field fieldToAdd : fieldsToAdd) {
|
||||
copyIntent.putExtra(fieldToAdd.extra, fieldToAdd.value);
|
||||
}
|
||||
copyIntent.setAction(fieldToCopy.getActionKey());
|
||||
copyIntent.putExtra(fieldToCopy.getExtraKey(), fieldToCopy);
|
||||
copyIntent.putParcelableArrayListExtra(EXTRA_FIELDS, fieldsToAdd);
|
||||
|
||||
return PendingIntent.getService(
|
||||
this, 0, copyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
private void newNotification(@Nullable String title, List<Field> fieldsToAdd) {
|
||||
private void newNotification(@Nullable String title, ArrayList<NotificationField> fieldsToAdd) {
|
||||
stopTask(countingDownTask);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID_COPYING)
|
||||
@@ -173,15 +132,15 @@ public class NotificationCopyingService extends Service {
|
||||
builder.setVisibility(Notification.VISIBILITY_SECRET);
|
||||
|
||||
if (fieldsToAdd.size() > 0) {
|
||||
Field field = fieldsToAdd.get(fieldsToAdd.size() - 1);
|
||||
NotificationField field = fieldsToAdd.get(0);
|
||||
builder.setContentText(field.copyText);
|
||||
builder.setContentIntent(getCopyPendingIntent(field, fieldsToAdd));
|
||||
|
||||
// Add extra actions without password
|
||||
List<Field> fieldsWithoutPassword = new ArrayList<>(fieldsToAdd);
|
||||
fieldsWithoutPassword.remove(field);
|
||||
// Add extra actions without 1st field
|
||||
List<NotificationField> fieldsWithoutFirstField = new ArrayList<>(fieldsToAdd);
|
||||
fieldsWithoutFirstField.remove(field);
|
||||
// Add extra actions
|
||||
for (Field fieldToAdd : fieldsWithoutPassword) {
|
||||
for (NotificationField fieldToAdd : fieldsWithoutFirstField) {
|
||||
builder.addAction(R.drawable.ic_key_white_24dp, fieldToAdd.label,
|
||||
getCopyPendingIntent(fieldToAdd, fieldsToAdd));
|
||||
}
|
||||
@@ -204,7 +163,7 @@ public class NotificationCopyingService extends Service {
|
||||
cleanNotificationTimer.start();
|
||||
}
|
||||
|
||||
private void copyField(Field fieldToCopy, List<Field> nextFields) {
|
||||
private void copyField(NotificationField fieldToCopy, ArrayList<NotificationField> nextFields) {
|
||||
stopTask(countingDownTask);
|
||||
stopTask(cleanNotificationTimer);
|
||||
|
||||
@@ -215,12 +174,9 @@ public class NotificationCopyingService extends Service {
|
||||
.setSmallIcon(R.drawable.ic_key_white_24dp)
|
||||
.setContentTitle(fieldToCopy.label);
|
||||
|
||||
// Remove the current field from the next fields
|
||||
if (nextFields.contains(fieldToCopy))
|
||||
nextFields.remove(fieldToCopy);
|
||||
// New action with next field if click
|
||||
if (nextFields.size() > 0) {
|
||||
Field nextField = nextFields.get(0);
|
||||
NotificationField nextField = nextFields.get(0);
|
||||
builder.setContentText(nextField.copyText);
|
||||
builder.setContentIntent(getCopyPendingIntent(nextField, nextFields));
|
||||
// Else tell to swipe for a clean
|
||||
@@ -260,7 +216,7 @@ public class NotificationCopyingService extends Service {
|
||||
});
|
||||
countingDownTask.start();
|
||||
|
||||
} catch (SamsungClipboardException e) {
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Clipboard can't be populate", e);
|
||||
}
|
||||
}
|
||||
@@ -270,33 +226,4 @@ public class NotificationCopyingService extends Service {
|
||||
task.interrupt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility class to manage fields in Notifications
|
||||
*/
|
||||
private class Field {
|
||||
String extra;
|
||||
String label;
|
||||
String copyText;
|
||||
String value;
|
||||
|
||||
Field(String extra, String value) {
|
||||
this.extra = extra;
|
||||
this.label = getLabelFromExtra(extra);
|
||||
this.copyText = getCopyTextFromExtra(extra);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Field field = (Field) o;
|
||||
return extra.equals(field.extra);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return extra.hashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2017 Jeremy Jamet / Kunzisoft.
|
||||
*
|
||||
* This file is part of KeePass DX.
|
||||
*
|
||||
* KeePass DX is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* KeePass DX is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with KeePass DX. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.keepassdroid.notifications;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.kunzisoft.keepass.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Utility class to manage fields in Notifications
|
||||
*/
|
||||
public class NotificationField implements Parcelable {
|
||||
|
||||
private static final String TAG = NotificationField.class.getName();
|
||||
|
||||
private NotificationFieldId id;
|
||||
String value;
|
||||
String label;
|
||||
String copyText;
|
||||
|
||||
public NotificationField(NotificationFieldId id, String value, Resources resources) {
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
this.label = getLabel(resources);
|
||||
this.copyText = getCopyText(resources);
|
||||
}
|
||||
|
||||
protected NotificationField(Parcel in) {
|
||||
id = NotificationFieldId.values()[in.readInt()];
|
||||
value = in.readString();
|
||||
label = in.readString();
|
||||
copyText = in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(id.ordinal());
|
||||
dest.writeString(value);
|
||||
dest.writeString(label);
|
||||
dest.writeString(copyText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<NotificationField> CREATOR = new Creator<NotificationField>() {
|
||||
@Override
|
||||
public NotificationField createFromParcel(Parcel in) {
|
||||
return new NotificationField(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NotificationField[] newArray(int size) {
|
||||
return new NotificationField[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
NotificationField field = (NotificationField) o;
|
||||
return id.equals(field.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
public enum NotificationFieldId {
|
||||
USERNAME, PASSWORD, FIELD_A, FIELD_B, FIELD_C;
|
||||
}
|
||||
|
||||
private static final String ACTION_COPY_PREFIX = "ACTION_COPY_";
|
||||
private static final String EXTRA_KEY_PREFIX = "EXTRA_";
|
||||
|
||||
/**
|
||||
* Return EXTRA_KEY link to ACTION_KEY, or null if ACTION_KEY is unknown
|
||||
*/
|
||||
public static @Nullable String getExtraKeyLinkToActionKey(String actionKey) {
|
||||
try {
|
||||
if (actionKey.startsWith(ACTION_COPY_PREFIX)) {
|
||||
String idName = actionKey.substring(ACTION_COPY_PREFIX.length(), actionKey.length());
|
||||
return getExtraKey(NotificationFieldId.valueOf(idName));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Can't get Extra Key from Action Key", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getActionKey(NotificationFieldId id) {
|
||||
return ACTION_COPY_PREFIX + id.name();
|
||||
}
|
||||
|
||||
public String getActionKey() {
|
||||
return getActionKey(id);
|
||||
}
|
||||
|
||||
private static String getExtraKey(NotificationFieldId id) {
|
||||
return EXTRA_KEY_PREFIX + id.name();
|
||||
}
|
||||
|
||||
public String getExtraKey() {
|
||||
return getExtraKey(id);
|
||||
}
|
||||
|
||||
public static List<String> getAllActionKeys() {
|
||||
List<String> actionKeys = new ArrayList<>();
|
||||
for (NotificationFieldId id : NotificationFieldId.values()) {
|
||||
actionKeys.add(getActionKey(id));
|
||||
}
|
||||
return actionKeys;
|
||||
}
|
||||
|
||||
public static List<String> getAllExtraKeys() {
|
||||
List<String> extraKeys = new ArrayList<>();
|
||||
for (NotificationFieldId id : NotificationFieldId.values()) {
|
||||
extraKeys.add(getExtraKey(id));
|
||||
}
|
||||
return extraKeys;
|
||||
}
|
||||
|
||||
private String getLabel(Resources resources) {
|
||||
switch (id) {
|
||||
case USERNAME:
|
||||
return resources.getString(R.string.entry_user_name);
|
||||
case PASSWORD:
|
||||
return resources.getString(R.string.entry_password);
|
||||
// TODO default
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String getCopyText(Resources resources) {
|
||||
switch (id) {
|
||||
case USERNAME:
|
||||
return resources.getString(R.string.copy_username);
|
||||
case PASSWORD:
|
||||
return resources.getString(R.string.copy_password);
|
||||
// TODO default
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user