Android app内截屏监听

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 下载地址:https://download.csdn.net/download/qq_29364417/21641402

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值