1.在 Application onCreate 方法设置 activity 生命周期监听
package com.example.myscreenshot;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
public class MyApp extends Application {
private static MyApp sInstance;
private Activity activeActivity;//应用中显示的 activity
public static MyApp getInstance() {
return sInstance;
}
@Override
public void onCreate() {
super.onCreate();
sInstance=this;
initActivityLifecycleCallbacks(this);
}
//全局监听 activity 生命周期
private void initActivityLifecycleCallbacks(Application application) {
application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
activeActivity = activity;
}
@Override
public void onActivityStarted(Activity activity) {
activeActivity = activity;
}
@Override
public void onActivityResumed(Activity activity) {
activeActivity = activity;
}
@Override
public void onActivityPaused(Activity activity) { }
@Override
public void onActivityStopped(Activity activity) { }
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { }
@Override
public void onActivityDestroyed(Activity activity) { }
});
}
//获取当前显示的activity
public Activity getActiveActivity() {
return activeActivity;
}
}
2.在 MainActivity 初始化 文件监听
package com.example.myscreenshot;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_PERMISSION_CODE = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Log.e("ScreenShotHelper", "onActivityResult=requestCode=" + requestCode);
if (requestCode == REQUEST_PERMISSION_CODE) {
ScreenShotHelper.getInstance().registerListener(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
ScreenShotHelper.getInstance().unregisterListener();
}
}
3.监听截屏
package com.example.myscreenshot;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Handler;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import androidx.core.app.ActivityCompat;
public class ScreenShotHelper {
private final String TAG=getClass().getName();
private static final String[] KEYWORDS = {
"screenshot", "screen_shot", "screen-shot", "screen shot",
"screencapture", "screen_capture", "screen-capture", "screen capture",
"screencap", "screen_cap", "screen-cap", "screen cap", "snap", "截屏"
};
/**
* 读取媒体数据库时需要读取的列
*/
private static final String[] MEDIA_PROJECTIONS = {
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.DATE_ADDED,
};
/**
* 内部存储器内容观察者
*/
private ContentObserver mInternalObserver;
/**
* 外部存储器内容观察者
*/
private ContentObserver mExternalObserver;
private ContentResolver mResolver;
private String lastData;
private Handler mHandler;
private static class Instance {
static ScreenShotHelper mInstance = new ScreenShotHelper();
}
public static ScreenShotHelper getInstance() {
return Instance.mInstance;
}
/**
* 注册监听
* @param mainActivity
*/
public void registerListener(MainActivity mainActivity) {
//上下文
mHandler = new Handler(mainActivity.getMainLooper());
// 初始化
mInternalObserver = new MediaContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, null);
mExternalObserver = new MediaContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null);
mResolver = mainActivity.getContentResolver();
// 添加监听
mResolver.registerContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, true, mInternalObserver);
mResolver.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, mExternalObserver);
}
//注销监听
public void unregisterListener() {
if (mResolver != null) {
mResolver.unregisterContentObserver(mInternalObserver);
mResolver.unregisterContentObserver(mExternalObserver);
}
}
private void handleMediaContentChange(Uri contentUri) {
Cursor cursor = null;
try {
// 数据改变时查询数据库中最后加入的一条数据
cursor = mResolver.query(
contentUri,
MEDIA_PROJECTIONS,
null,
null,
MediaStore.Images.ImageColumns.DATE_ADDED + " desc limit 1"
);
if (cursor == null) {
return;
}
if (!cursor.moveToFirst()) {
return;
}
// 获取各列的索引
int dataIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
int dateTakenIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_TAKEN);
int dateAddIndex = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_ADDED);
// 获取行数据
final String data = cursor.getString(dataIndex);
long dateTaken = cursor.getLong(dateTakenIndex);
long dateAdded = cursor.getLong(dateAddIndex);
if (data.length() > 0) {
if (TextUtils.equals(lastData, data)) {
//更改资源文件名也会触发,并且传递过来的是之前的截屏文件,所以只对分钟以内的有效
if (System.currentTimeMillis() - dateTaken < 3 * 3600) {
mHandler.removeCallbacks(shotCallBack);
mHandler.postDelayed(shotCallBack, 500);
}
} else if (dateTaken == 0 || dateTaken == dateAdded * 1000) {
mHandler.removeCallbacks(shotCallBack);
} else if (checkScreenShot(data)) {
mHandler.removeCallbacks(shotCallBack);
lastData = data;
mHandler.postDelayed(shotCallBack, 500);
}
}
} catch (Exception e) {
Log.e(TAG, "ex==" + e.getMessage());
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
}
private Runnable shotCallBack = new Runnable() {
@Override
public void run() {
final String path = lastData;
if (path != null && path.length() > 0) {
Log.e(TAG, "run=path==" + path);
//逻辑处理区
Dialog dialog=new Dialog(MyApp.getInstance().getActiveActivity());
ImageView imageView = new ImageView(MyApp.getInstance().getActiveActivity());
imageView.setImageBitmap(BitmapFactory.decodeFile(path));
dialog.setContentView(imageView);
dialog.show();
}
}
};
/**
* 根据包含关键字判断是否是截屏
*/
private boolean checkScreenShot(String data) {
if (data == null || data.length() < 2) {
return false;
}
data = data.toLowerCase();
for (String keyWork : KEYWORDS) {
if (data.contains(keyWork)) {
return true;
}
}
return false;
}
private class MediaContentObserver extends ContentObserver {
private Uri mContentUri;
private long mLastTime;
MediaContentObserver(Uri contentUri, Handler handler) {
super(handler);
mContentUri = contentUri;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
try {
//满足以下条件才去查询:1.应用是否可见 2.读写权限 是否已开启 3.是否回调多次(某些机型会出现)
boolean isVisible = MyApp.getInstance().getActiveActivity() != null && MyApp.getInstance().getActiveActivity().getWindow().getDecorView().getVisibility() == View.VISIBLE;//应用是否可见
boolean isGranted = isGrantedPermission(MyApp.getInstance().getActiveActivity());//读写权限 是否已开启
boolean isFast = (System.currentTimeMillis() - mLastTime) > 3000;//是否回调多次(某些机型会出现)
Log.e(TAG, "onChange==" + selfChange + ",activeActivity=" + MyApp.getInstance().getActiveActivity().getClass().getName() + ",isVisible=" + isVisible + ",isGranted=" + isGranted + ",isFast=" + isFast);
if (isVisible && isGranted && isFast) {
handleMediaContentChange(mContentUri);
mLastTime = System.currentTimeMillis();
}
} catch (Exception e) {
Log.e(TAG, "ex==" + e.getMessage());
}
}
}
private boolean isGrantedPermission(Activity activity){
return ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
}
4. AndroidManifest.xml 文件 设置 读写权限
BitmapFactory.decodeFile(path) 高版本需要此项:android:requestLegacyExternalStorage="true"
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myscreenshot">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:requestLegacyExternalStorage="true"
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Demo?
|