Android 中任何第三方軟件都可訪問剪切板內容,雖然高版本對剪切板做了訪問限制,但是還是需要照顧一下低版本的,解決方法就是要禁用EditText的複製粘貼功能,讓用戶不能向剪切板中放置內容。下邊就來說說具體實現吧。
1、自定義NoMenuEditText 繼承自AppCompatEditText
2、重寫isSuggestionsEnabled方法
並返回false
創建canPaste()
方法並返回false。該方法是一個隱藏方法
3、實現ActionMode.Callback回調
private class ActionModeCallbackInterceptor implements ActionMode.Callback {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
}
4、設置回調
this.setLongClickable(false);
//this.setTextIsSelectable(false);
this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
//使用該方式基本可以實現禁用粘貼複製功能,6.0以上可用
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
this.setCustomInsertionActionModeCallback(new ActionModeCallbackInterceptor());
}
使用以上方式即可禁用掉EditText的複製粘貼功能,但是長按EditTeit控件中的文本時光標會有變化,並且該方式只能在6.0以上版本中使用。如果以上方式不能滿足你的需求,請看以下方式:
1、2、3步同上,修改第4步不再用 this.setCustomInsertionActionModeCallback(new ActionModeCallbackInterceptor())方法。
使用以下方式(反射)代替:
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
NoMenuEditText.this.clearFocus();
return false;
}
});
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// setInsertionDisabled when user touches the view
this.setInsertionDisabled();
}
return super.onTouchEvent(event);
}
private void setInsertionDisabled() {
try {
Field editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
Object editorObject = editorField.get(this);
@SuppressLint("PrivateApi") Class editorClass = Class.forName("android.widget.Editor");
Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
mInsertionControllerEnabledField.setAccessible(true);
mInsertionControllerEnabledField.set(editorObject, false);
} catch (Exception ignored) {
}
}
使用這種方式即可解決第一種方式的版本兼容問題,並且長按EditText控件中的文本光標也不會有任何變化,完美解決剪切板敏感信息泄露問題。希望以上方案對你有所幫助。
伸手黨請看如下完整代碼(別忘了點個贊哦):
@SuppressLint("NewApi")
public class NoMenuEditText extends AppCompatEditText {
private final Context context;
/**
* 該方法爲隱藏方法
*/
boolean canPaste() {
return false;
}
@Override
public boolean isSuggestionsEnabled() {
return false;
}
public NoMenuEditText(Context context) {
super(context);
this.context = context;
init();
}
public NoMenuEditText(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public NoMenuEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init();
}
@SuppressLint("ClickableViewAccessibility")
private void init() {
this.setLongClickable(false);
//this.setTextIsSelectable(false);
this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
//使用該方式基本可以實現禁用粘貼複製功能,6.0以上可用
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// this.setCustomInsertionActionModeCallback(new ActionModeCallbackInterceptor());
// }
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
NoMenuEditText.this.clearFocus();
return false;
}
});
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// setInsertionDisabled when user touches the view
this.setInsertionDisabled();
}
return super.onTouchEvent(event);
}
private void setInsertionDisabled() {
try {
Field editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
Object editorObject = editorField.get(this);
@SuppressLint("PrivateApi") Class editorClass = Class.forName("android.widget.Editor");
Field mInsertionControllerEnabledField = editorClass.getDeclaredField("mInsertionControllerEnabled");
mInsertionControllerEnabledField.setAccessible(true);
mInsertionControllerEnabledField.set(editorObject, false);
} catch (Exception ignored) {
}
}
/**
* Prevents the action bar (top horizontal bar with cut,copy,paste,etc.)
* from appearing by intercepting the callback that would cause it to be
* created,and returning false.
*/
private class ActionModeCallbackInterceptor implements ActionMode.Callback {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
}
}
參考:https://stackoverflow.com/questions/41673185/disable-edittext-context-menu