Nac*_*ing 14 android screenshot detect capture
我目前正在开发Android应用程序,并想知道如何检测屏幕截图.我尝试使用FileObserver,但问题是检测到所有事件(当设备进入睡眠状态,消息等).如何只检测截图?
先感谢您 !
ali*_*dro 24
你是如何FileObserver用来检测屏幕截图的?使用时FileObserver,仅监视屏幕截图目录中的文件创建事件.
String path = Environment.getExternalStorageDirectory()
+ File.separator + Environment.DIRECTORY_PICTURES
+ File.separator + "Screenshots" + File.separator;
Log.d(TAG, path);
FileObserver fileObserver = new FileObserver(path, FileObserver.CREATE) {
@Override
public void onEvent(int event, String path) {
Log.d(TAG, event + " " + path);
}
};
fileObserver.startWatching();
Run Code Online (Sandbox Code Playgroud)
不要忘记声明相应的权限来访问SD卡中的内容.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Run Code Online (Sandbox Code Playgroud)
另一种检测屏幕截图的方法是使用ContentObserver,因为屏幕截图后会有一条记录插入系统媒体数据库.以下是ContentObserver用于监视事件的代码段.通过使用ContentObserver,没有必要声明write/read external storage权限,但你必须对文件名做一些过滤,以确保它是一个屏幕截图事件.
HandlerThread handlerThread = new HandlerThread("content_observer");
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
getContentResolver().registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
true,
new ContentObserver(handler) {
@Override
public boolean deliverSelfNotifications() {
Log.d(TAG, "deliverSelfNotifications");
return super.deliverSelfNotifications();
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
Log.d(TAG, "onChange " + uri.toString());
if (uri.toString().matches(MediaStore.Images.Media.EXTERNAL_CONTENT_URI.toString() + "/[0-9]+")) {
Cursor cursor = null;
try {
cursor = getContentResolver().query(uri, new String[] {
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.DATA
}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final String fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
final String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
// TODO: apply filter on the file name to ensure it's screen shot event
Log.d(TAG, "screen shot added " + fileName + " " + path);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
}
super.onChange(selfChange, uri);
}
}
);
Run Code Online (Sandbox Code Playgroud)
更新
如果您使用第二种方法,则必须READ_EXTERNAL_STORAGE在Android M版本之后请求,否则它将抛出SecurityException.有关如何请求运行时权限的更多信息,请参阅此处.
我改进了 alijandro 评论中的代码,使其易于使用,并修复了内容观察器检测到来自相机的图像时的问题(应该只是屏幕截图图像)。然后将其包装到委托类中以方便使用。
\n\n\xe2\x80\xa2 ScreenshotDetectionDelegate.java
\n\npublic class ScreenshotDetectionDelegate {\n private WeakReference<Activity> activityWeakReference;\n private ScreenshotDetectionListener listener;\n\n public ScreenshotDetectionDelegate(Activity activityWeakReference, ScreenshotDetectionListener listener) {\n this.activityWeakReference = new WeakReference<>(activityWeakReference);\n this.listener = listener;\n }\n\n public void startScreenshotDetection() {\n activityWeakReference.get()\n .getContentResolver()\n .registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, contentObserver);\n }\n\n public void stopScreenshotDetection() {\n activityWeakReference.get().getContentResolver().unregisterContentObserver(contentObserver);\n }\n\n private ContentObserver contentObserver = new ContentObserver(new Handler()) {\n @Override\n public boolean deliverSelfNotifications() {\n return super.deliverSelfNotifications();\n }\n\n @Override\n public void onChange(boolean selfChange) {\n super.onChange(selfChange);\n }\n\n @Override\n public void onChange(boolean selfChange, Uri uri) {\n super.onChange(selfChange, uri);\n if (isReadExternalStoragePermissionGranted()) {\n String path = getFilePathFromContentResolver(activityWeakReference.get(), uri);\n if (isScreenshotPath(path)) {\n onScreenCaptured(path);\n }\n } else {\n onScreenCapturedWithDeniedPermission();\n }\n }\n };\n\n private void onScreenCaptured(String path) {\n if (listener != null) {\n listener.onScreenCaptured(path);\n }\n }\n\n private void onScreenCapturedWithDeniedPermission() {\n if (listener != null) {\n listener.onScreenCapturedWithDeniedPermission();\n }\n }\n\n private boolean isScreenshotPath(String path) {\n return path != null && path.toLowerCase().contains("screenshots");\n }\n\n private String getFilePathFromContentResolver(Context context, Uri uri) {\n try {\n Cursor cursor = context.getContentResolver().query(uri, new String[]{\n MediaStore.Images.Media.DISPLAY_NAME,\n MediaStore.Images.Media.DATA\n }, null, null, null);\n if (cursor != null && cursor.moveToFirst()) {\n String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));\n cursor.close();\n return path;\n }\n } catch (IllegalStateException ignored) {\n }\n return null;\n }\n\n private boolean isReadExternalStoragePermissionGranted() {\n return ContextCompat.checkSelfPermission(activityWeakReference.get(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;\n }\n\n public interface ScreenshotDetectionListener {\n void onScreenCaptured(String path);\n\n void onScreenCapturedWithDeniedPermission();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\xe2\x80\xa2 ScreenshotDetectionActivity.java
\n\nimport android.Manifest;\nimport android.content.pm.PackageManager;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.ActivityCompat;\nimport android.support.v4.content.ContextCompat;\nimport android.support.v7.app.AppCompatActivity;\nimport android.widget.Toast;\n\npublic abstract class ScreenshotDetectionActivity extends AppCompatActivity implements ScreenshotDetectionDelegate.ScreenshotDetectionListener {\n private static final int REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION = 3009;\n\n private ScreenshotDetectionDelegate screenshotDetectionDelegate = new ScreenshotDetectionDelegate(this, this);\n\n @Override\n protected void onCreate(@Nullable Bundle savedInstanceState) {\n super.onCreate(savedInstanceState);\n checkReadExternalStoragePermission();\n }\n\n @Override\n protected void onStart() {\n super.onStart();\n screenshotDetectionDelegate.startScreenshotDetection();\n }\n\n @Override\n protected void onStop() {\n super.onStop();\n screenshotDetectionDelegate.stopScreenshotDetection();\n }\n\n @Override\n public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {\n switch (requestCode) {\n case REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION:\n if (grantResults[0] == PackageManager.PERMISSION_DENIED) {\n showReadExternalStoragePermissionDeniedMessage();\n }\n break;\n default:\n super.onRequestPermissionsResult(requestCode, permissions, grantResults);\n }\n }\n\n @Override\n public void onScreenCaptured(String path) {\n // Do something when screen was captured\n }\n\n @Override\n public void onScreenCapturedWithDeniedPermission() {\n // Do something when screen was captured but read external storage permission has denied\n }\n\n private void checkReadExternalStoragePermission() {\n if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {\n requestReadExternalStoragePermission();\n }\n }\n\n private void requestReadExternalStoragePermission() {\n ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_READ_EXTERNAL_STORAGE_PERMISSION);\n }\n\n private void showReadExternalStoragePermissionDeniedMessage() {\n Toast.makeText(this, "Read external storage permission has denied", Toast.LENGTH_SHORT).show();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\xe2\x80\xa2 MainActivity.java
\n\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.Toast;\n\npublic class MainActivity extends ScreenshotDetectionActivity {\n @Override\n protected void onCreate(Bundle savedInstanceState) {\n super.onCreate(savedInstanceState);\n setContentView(R.layout.activity_main);\n }\n\n @Override\n public void onScreenCaptured(String path) {\n Toast.make(this, path, Toast.LENGTH_SHORT).show();\n }\n\n @Override\n public void onScreenCapturedWithDeniedPermission() {\n Toast.make(this, "Please grant read external storage permission for screenshot detection", Toast.LENGTH_SHORT).show();\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
8910 次 |
| 最近记录: |