mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Upgrade clipboard and timeout
This commit is contained in:
@@ -21,22 +21,11 @@
|
||||
package com.keepassdroid.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.SpannableString;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
@@ -50,11 +39,10 @@ import com.keepassdroid.compat.ActivityCompat;
|
||||
import com.keepassdroid.database.Database;
|
||||
import com.keepassdroid.database.PwDatabase;
|
||||
import com.keepassdroid.database.PwEntry;
|
||||
import com.keepassdroid.database.exception.SamsungClipboardException;
|
||||
import com.keepassdroid.password.PasswordActivity;
|
||||
import com.keepassdroid.services.NotificationCopyingService;
|
||||
import com.keepassdroid.settings.PreferencesUtil;
|
||||
import com.keepassdroid.tasks.UIToastTask;
|
||||
import com.keepassdroid.timeout.ClipboardHelper;
|
||||
import com.keepassdroid.utils.EmptyUtils;
|
||||
import com.keepassdroid.utils.MenuUtil;
|
||||
import com.keepassdroid.utils.Types;
|
||||
@@ -64,8 +52,6 @@ import com.kunzisoft.keepass.R;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.keepassdroid.settings.PreferencesUtil.isClipboardNotificationsEnable;
|
||||
@@ -73,19 +59,16 @@ import static com.keepassdroid.settings.PreferencesUtil.isClipboardNotifications
|
||||
public class EntryActivity extends LockingHideActivity {
|
||||
public static final String KEY_ENTRY = "entry";
|
||||
|
||||
public static final String COPY_USERNAME = "com.keepassdroid.copy_username";
|
||||
public static final String COPY_PASSWORD = "com.keepassdroid.copy_password";
|
||||
|
||||
private ImageView titleIconView;
|
||||
private TextView titleView;
|
||||
private EntryContentsView entryContentsView;
|
||||
|
||||
protected PwEntry mEntry;
|
||||
private Timer mTimer = new Timer();
|
||||
private boolean mShowPassword;
|
||||
private BroadcastReceiver mIntentReceiver;
|
||||
protected boolean readOnly = false;
|
||||
|
||||
private ClipboardHelper clipboardHelper;
|
||||
|
||||
public static void launch(Activity act, PwEntry pw) {
|
||||
Intent intent = new Intent(act, EntryActivity.class);
|
||||
intent.putExtra(KEY_ENTRY, Types.UUIDtoBytes(pw.getUUID()));
|
||||
@@ -141,68 +124,36 @@ public class EntryActivity extends LockingHideActivity {
|
||||
|
||||
// Setup Edit Buttons
|
||||
View edit = findViewById(R.id.entry_edit);
|
||||
edit.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
public void onClick(View v) {
|
||||
EntryEditActivity.Launch(EntryActivity.this, mEntry);
|
||||
}
|
||||
|
||||
});
|
||||
edit.setOnClickListener(v -> EntryEditActivity.Launch(EntryActivity.this, mEntry));
|
||||
if (readOnly) {
|
||||
edit.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// If notifications enabled in settings
|
||||
if (isClipboardNotificationsEnable(getApplicationContext())) {
|
||||
if (mEntry.getPassword().length() > 0) {
|
||||
// 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) {
|
||||
// Init the clipboard helper
|
||||
clipboardHelper = new ClipboardHelper(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// If notifications enabled in settings
|
||||
// Don't if application timeout
|
||||
if (!App.isShutdown() && isClipboardNotificationsEnable(getApplicationContext())) {
|
||||
if (mEntry.getPassword().length() > 0) {
|
||||
// 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());
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
if (mEntry.getTitle() != null)
|
||||
intent.putExtra(NotificationCopyingService.EXTRA_ENTRY_TITLE, mEntry.getTitle());
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if ( action != null) {
|
||||
if (action.equals(COPY_USERNAME)) {
|
||||
String username = mEntry.getUsername();
|
||||
if (username.length() > 0) {
|
||||
timeoutCopyToClipboard(username);
|
||||
}
|
||||
} else if (action.equals(COPY_PASSWORD)) {
|
||||
String password = mEntry.getPassword();
|
||||
if (password.length() > 0) {
|
||||
timeoutCopyToClipboard(password);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(COPY_USERNAME);
|
||||
filter.addAction(COPY_PASSWORD);
|
||||
registerReceiver(mIntentReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
// These members might never get initialized if the app timed out
|
||||
if ( mIntentReceiver != null ) {
|
||||
unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void populateTitle(Drawable drawIcon, String text) {
|
||||
titleIconView.setImageDrawable(drawIcon);
|
||||
@@ -219,22 +170,16 @@ public class EntryActivity extends LockingHideActivity {
|
||||
|
||||
// Assign basic fields
|
||||
entryContentsView.assignUserName(mEntry.getUsername(true, pm));
|
||||
entryContentsView.assignUserNameCopyListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
timeoutCopyToClipboard(mEntry.getUsername(true, App.getDB().pm),
|
||||
getString(R.string.copy_field, getString(R.string.entry_user_name)));
|
||||
}
|
||||
});
|
||||
entryContentsView.assignUserNameCopyListener(view ->
|
||||
clipboardHelper.timeoutCopyToClipboard(mEntry.getUsername(true, App.getDB().pm),
|
||||
getString(R.string.copy_field, getString(R.string.entry_user_name)))
|
||||
);
|
||||
|
||||
entryContentsView.assignPassword(mEntry.getPassword(true, pm));
|
||||
entryContentsView.assignPasswordCopyListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
timeoutCopyToClipboard(mEntry.getPassword(true, App.getDB().pm),
|
||||
getString(R.string.copy_field, getString(R.string.entry_password)));
|
||||
}
|
||||
});
|
||||
entryContentsView.assignPasswordCopyListener(view ->
|
||||
clipboardHelper.timeoutCopyToClipboard(mEntry.getPassword(true, App.getDB().pm),
|
||||
getString(R.string.copy_field, getString(R.string.entry_password)))
|
||||
);
|
||||
|
||||
entryContentsView.assignURL(mEntry.getUrl(true, pm));
|
||||
|
||||
@@ -247,12 +192,8 @@ public class EntryActivity extends LockingHideActivity {
|
||||
for (Map.Entry<String, String> field : mEntry.getExtraFields(pm).entrySet()) {
|
||||
final String label = field.getKey();
|
||||
final String value = field.getValue();
|
||||
entryContentsView.addExtraField(label, value, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
timeoutCopyToClipboard(value, getString(R.string.copy_field, label));
|
||||
}
|
||||
});
|
||||
entryContentsView.addExtraField(label, value, view ->
|
||||
clipboardHelper.timeoutCopyToClipboard(value, getString(R.string.copy_field, label)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,30 +304,6 @@ public class EntryActivity extends LockingHideActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void timeoutCopyToClipboard(String text) {
|
||||
timeoutCopyToClipboard(text, "");
|
||||
}
|
||||
|
||||
private void timeoutCopyToClipboard(String text, String toastString) {
|
||||
if (!toastString.isEmpty())
|
||||
Toast.makeText(EntryActivity.this, toastString, Toast.LENGTH_LONG).show();
|
||||
|
||||
try {
|
||||
Util.copyToClipboard(this, text);
|
||||
} catch (SamsungClipboardException e) {
|
||||
showSamsungDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String sClipClear = prefs.getString(getString(R.string.clipboard_timeout_key), getString(R.string.clipboard_timeout_default));
|
||||
|
||||
long clipClearTime = Long.parseLong(sClipClear);
|
||||
|
||||
if ( clipClearTime > 0 ) {
|
||||
mTimer.schedule(new ClearClipboardTask(this, text), clipClearTime);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
@@ -399,55 +316,4 @@ public class EntryActivity extends LockingHideActivity {
|
||||
*/
|
||||
super.finish();
|
||||
}
|
||||
|
||||
// Setup to allow the toast to happen in the foreground
|
||||
final Handler uiThreadCallback = new Handler();
|
||||
|
||||
// Task which clears the clipboard, and sends a toast to the foreground.
|
||||
private class ClearClipboardTask extends TimerTask {
|
||||
|
||||
private final String mClearText;
|
||||
private final Context mCtx;
|
||||
|
||||
ClearClipboardTask(Context ctx, String clearText) {
|
||||
mClearText = clearText;
|
||||
mCtx = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
String currentClip = Util.getClipboard(mCtx);
|
||||
|
||||
if ( currentClip.equals(mClearText) ) {
|
||||
try {
|
||||
Util.copyToClipboard(mCtx, "");
|
||||
uiThreadCallback.post(new UIToastTask(mCtx, R.string.ClearClipboard));
|
||||
} catch (SamsungClipboardException e) {
|
||||
uiThreadCallback.post(new UIToastTask(mCtx, R.string.clipboard_error_clear));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showSamsungDialog() {
|
||||
String text = getString(R.string.clipboard_error).concat(System.getProperty("line.separator")).concat(getString(R.string.clipboard_error_url));
|
||||
SpannableString s = new SpannableString(text);
|
||||
TextView tv = new TextView(this);
|
||||
tv.setText(s);
|
||||
tv.setAutoLinkMask(RESULT_OK);
|
||||
tv.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
Linkify.addLinks(s, Linkify.WEB_URLS);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.clipboard_error_title)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
}
|
||||
})
|
||||
.setView(tv)
|
||||
.show();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ public abstract class LockingActivity extends StylishActivity {
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// TODO Solve timeout shutdown
|
||||
TimeoutHelper.checkShutdown(this);
|
||||
TimeoutHelper.recordTime(this);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
@@ -15,6 +13,8 @@ import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import com.keepassdroid.database.exception.SamsungClipboardException;
|
||||
import com.keepassdroid.timeout.ClipboardHelper;
|
||||
import com.kunzisoft.keepass.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -39,7 +39,7 @@ public class NotificationCopyingService extends Service {
|
||||
public static final String ACTION_CLEAN_CLIPBOARD = "ACTION_CLEAN_CLIPBOARD";
|
||||
|
||||
private NotificationManager notificationManager;
|
||||
private ClipboardManager clipboardManager;
|
||||
private ClipboardHelper clipboardHelper;
|
||||
private Thread cleanNotificationTimer;
|
||||
private Thread countingDownTask;
|
||||
private int notificationId = 1;
|
||||
@@ -57,7 +57,7 @@ public class NotificationCopyingService extends Service {
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
clipboardHelper = new ClipboardHelper(this);
|
||||
|
||||
// Create notification channel for Oreo+
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
@@ -98,8 +98,11 @@ public class NotificationCopyingService extends Service {
|
||||
|
||||
} else if (ACTION_CLEAN_CLIPBOARD.equals(intent.getAction())) {
|
||||
stopTask(countingDownTask);
|
||||
cleanPassword();
|
||||
|
||||
try {
|
||||
clipboardHelper.cleanClipboard();
|
||||
} catch (SamsungClipboardException e) {
|
||||
Log.e(TAG, "Clipboard can't be cleaned", e);
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "unknown action");
|
||||
}
|
||||
@@ -159,19 +162,11 @@ public class NotificationCopyingService extends Service {
|
||||
this, 0, copyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
private void addActionsToBuilder(NotificationCompat.Builder builder, List<Field> fieldsToAdd) {
|
||||
// Add extra actions
|
||||
for (Field fieldToAdd : fieldsToAdd) {
|
||||
builder.addAction(R.drawable.notify, fieldToAdd.label,
|
||||
getCopyPendingIntent(fieldToAdd, fieldsToAdd));
|
||||
}
|
||||
}
|
||||
|
||||
private void newNotification(@Nullable String title, List<Field> fieldsToAdd) {
|
||||
stopTask(countingDownTask);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID_COPYING)
|
||||
.setSmallIcon(R.drawable.notify);
|
||||
.setSmallIcon(R.drawable.ic_key_white_24dp);
|
||||
if (title != null)
|
||||
builder.setContentTitle(title);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||
@@ -182,8 +177,14 @@ public class NotificationCopyingService extends Service {
|
||||
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
|
||||
addActionsToBuilder(builder, fieldsToAdd);
|
||||
for (Field fieldToAdd : fieldsWithoutPassword) {
|
||||
builder.addAction(R.drawable.ic_key_white_24dp, fieldToAdd.label,
|
||||
getCopyPendingIntent(fieldToAdd, fieldsToAdd));
|
||||
}
|
||||
}
|
||||
|
||||
notificationManager.cancel(notificationId);
|
||||
@@ -207,59 +208,61 @@ public class NotificationCopyingService extends Service {
|
||||
stopTask(countingDownTask);
|
||||
stopTask(cleanNotificationTimer);
|
||||
|
||||
copyToClipboard(fieldToCopy.label, fieldToCopy.value);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID_COPYING)
|
||||
.setSmallIcon(R.drawable.ic_key_white_24dp)
|
||||
.setContentTitle(fieldToCopy.label);
|
||||
try {
|
||||
clipboardHelper.copyToClipboard(fieldToCopy.label, fieldToCopy.value);
|
||||
|
||||
// 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);
|
||||
builder.setContentText(nextField.copyText);
|
||||
builder.setContentIntent(getCopyPendingIntent(nextField, nextFields));
|
||||
// Else tell to swipe for a clean
|
||||
} else {
|
||||
builder.setContentText(getString(R.string.clipboard_swipe_clean));
|
||||
}
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID_COPYING)
|
||||
.setSmallIcon(R.drawable.ic_key_white_24dp)
|
||||
.setContentTitle(fieldToCopy.label);
|
||||
|
||||
Intent cleanIntent = new Intent(this, NotificationCopyingService.class);
|
||||
cleanIntent.setAction(ACTION_CLEAN_CLIPBOARD);
|
||||
PendingIntent cleanPendingIntent = PendingIntent.getService(
|
||||
this, 0, cleanIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setDeleteIntent(cleanPendingIntent);
|
||||
|
||||
int myNotificationId = notificationId;
|
||||
|
||||
countingDownTask = new Thread(() -> {
|
||||
int maxPos = 100;
|
||||
long posDurationMills = notificationTimeoutMilliSecs / maxPos;
|
||||
for (int pos = maxPos; pos > 0; --pos) {
|
||||
builder.setProgress(maxPos, pos, false);
|
||||
notificationManager.notify(myNotificationId, builder.build());
|
||||
try {
|
||||
Thread.sleep(posDurationMills);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
// 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);
|
||||
builder.setContentText(nextField.copyText);
|
||||
builder.setContentIntent(getCopyPendingIntent(nextField, nextFields));
|
||||
// Else tell to swipe for a clean
|
||||
} else {
|
||||
builder.setContentText(getString(R.string.clipboard_swipe_clean));
|
||||
}
|
||||
countingDownTask = null;
|
||||
notificationManager.cancel(myNotificationId);
|
||||
// Clean password only if no next field
|
||||
if (nextFields.size() <= 0)
|
||||
cleanPassword();
|
||||
});
|
||||
countingDownTask.start();
|
||||
}
|
||||
|
||||
private void copyToClipboard(String name, String value) {
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(name, value));
|
||||
}
|
||||
Intent cleanIntent = new Intent(this, NotificationCopyingService.class);
|
||||
cleanIntent.setAction(ACTION_CLEAN_CLIPBOARD);
|
||||
PendingIntent cleanPendingIntent = PendingIntent.getService(
|
||||
this, 0, cleanIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setDeleteIntent(cleanPendingIntent);
|
||||
|
||||
private void cleanPassword() {
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText("",""));
|
||||
int myNotificationId = notificationId;
|
||||
|
||||
countingDownTask = new Thread(() -> {
|
||||
int maxPos = 100;
|
||||
long posDurationMills = notificationTimeoutMilliSecs / maxPos;
|
||||
for (int pos = maxPos; pos > 0; --pos) {
|
||||
builder.setProgress(maxPos, pos, false);
|
||||
notificationManager.notify(myNotificationId, builder.build());
|
||||
try {
|
||||
Thread.sleep(posDurationMills);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
countingDownTask = null;
|
||||
notificationManager.cancel(myNotificationId);
|
||||
// Clean password only if no next field
|
||||
if (nextFields.size() <= 0)
|
||||
try {
|
||||
clipboardHelper.cleanClipboard();
|
||||
} catch (SamsungClipboardException e) {
|
||||
Log.e(TAG, "Clipboard can't be cleaned", e);
|
||||
}
|
||||
});
|
||||
countingDownTask.start();
|
||||
|
||||
} catch (SamsungClipboardException e) {
|
||||
Log.e(TAG, "Clipboard can't be populate", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopTask(Thread task) {
|
||||
|
||||
158
app/src/main/java/com/keepassdroid/timeout/ClipboardHelper.java
Normal file
158
app/src/main/java/com/keepassdroid/timeout/ClipboardHelper.java
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2018 Brian Pellin, 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.timeout;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.SpannableString;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.keepassdroid.database.exception.SamsungClipboardException;
|
||||
import com.keepassdroid.tasks.UIToastTask;
|
||||
import com.kunzisoft.keepass.R;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ClipboardHelper {
|
||||
|
||||
private Context context;
|
||||
private ClipboardManager clipboardManager;
|
||||
|
||||
private Timer mTimer = new Timer();
|
||||
|
||||
public ClipboardHelper(Context context) {
|
||||
this.context = context;
|
||||
this.clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
}
|
||||
|
||||
public void timeoutCopyToClipboard(String text) {
|
||||
timeoutCopyToClipboard(text, "");
|
||||
}
|
||||
|
||||
public void timeoutCopyToClipboard(String text, String toastString) {
|
||||
if (!toastString.isEmpty())
|
||||
Toast.makeText(context, toastString, Toast.LENGTH_LONG).show();
|
||||
try {
|
||||
copyToClipboard(text);
|
||||
} catch (SamsungClipboardException e) {
|
||||
showSamsungDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String sClipClear = prefs.getString(context.getString(R.string.clipboard_timeout_key),
|
||||
context.getString(R.string.clipboard_timeout_default));
|
||||
|
||||
long clipClearTime = Long.parseLong(sClipClear);
|
||||
|
||||
if ( clipClearTime > 0 ) {
|
||||
mTimer.schedule(new ClearClipboardTask(context, text), clipClearTime);
|
||||
}
|
||||
}
|
||||
|
||||
public CharSequence getClipboard(Context context) {
|
||||
if (clipboardManager.hasPrimaryClip()) {
|
||||
ClipData data = clipboardManager.getPrimaryClip();
|
||||
if (data.getItemCount() > 0) {
|
||||
CharSequence text = data.getItemAt(0).coerceToText(context);
|
||||
if (text != null) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public void copyToClipboard(String value) throws SamsungClipboardException {
|
||||
copyToClipboard("", value);
|
||||
}
|
||||
|
||||
public void copyToClipboard(String label, String value) throws SamsungClipboardException {
|
||||
try {
|
||||
clipboardManager.setPrimaryClip(ClipData.newPlainText(label, value));
|
||||
} catch (NullPointerException e) {
|
||||
throw new SamsungClipboardException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanClipboard() throws SamsungClipboardException {
|
||||
cleanClipboard("");
|
||||
}
|
||||
|
||||
public void cleanClipboard(String label) throws SamsungClipboardException {
|
||||
copyToClipboard(label,"");
|
||||
}
|
||||
|
||||
|
||||
// Setup to allow the toast to happen in the foreground
|
||||
private final Handler uiThreadCallback = new Handler();
|
||||
|
||||
// Task which clears the clipboard, and sends a toast to the foreground.
|
||||
private class ClearClipboardTask extends TimerTask {
|
||||
|
||||
private final String mClearText;
|
||||
private final Context mCtx;
|
||||
|
||||
ClearClipboardTask(Context ctx, String clearText) {
|
||||
mClearText = clearText;
|
||||
mCtx = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
String currentClip = getClipboard(mCtx).toString();
|
||||
if ( currentClip.equals(mClearText) ) {
|
||||
try {
|
||||
cleanClipboard();
|
||||
uiThreadCallback.post(new UIToastTask(mCtx, R.string.ClearClipboard));
|
||||
} catch (SamsungClipboardException e) {
|
||||
uiThreadCallback.post(new UIToastTask(mCtx, R.string.clipboard_error_clear));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showSamsungDialog() {
|
||||
String text = context.getString(R.string.clipboard_error).concat(System.getProperty("line.separator"))
|
||||
.concat(context.getString(R.string.clipboard_error_url));
|
||||
SpannableString s = new SpannableString(text);
|
||||
TextView tv = new TextView(context);
|
||||
tv.setText(s);
|
||||
tv.setAutoLinkMask(Activity.RESULT_OK);
|
||||
tv.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
Linkify.addLinks(s, Linkify.WEB_URLS);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.clipboard_error_title)
|
||||
.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss())
|
||||
.setView(tv)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class TimeoutHelper {
|
||||
|
||||
public static void checkShutdown(Activity act) {
|
||||
if ( App.isShutdown() && App.getDB().Loaded() ) {
|
||||
Log.e(TAG, "Shutdown " + act.getLocalClassName() + " after inactivity");
|
||||
Log.i(TAG, "Shutdown " + act.getLocalClassName() + " after inactivity");
|
||||
act.setResult(PasswordActivity.RESULT_EXIT_LOCK);
|
||||
act.finish();
|
||||
}
|
||||
|
||||
@@ -20,39 +20,17 @@
|
||||
package com.keepassdroid.utils;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Typeface;
|
||||
import android.net.Uri;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.keepassdroid.database.exception.SamsungClipboardException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class Util {
|
||||
public static String getClipboard(Context context) {
|
||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
CharSequence csText = clipboard.getText();
|
||||
if (csText == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return csText.toString();
|
||||
}
|
||||
|
||||
public static void copyToClipboard(Context context, String text) throws SamsungClipboardException {
|
||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
|
||||
try {
|
||||
clipboard.setText(text);
|
||||
} catch (NullPointerException e) {
|
||||
throw new SamsungClipboardException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void gotoUrl(Context context, String url) throws ActivityNotFoundException {
|
||||
if ( url != null && url.length() > 0 ) {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
Reference in New Issue
Block a user