IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android进阶之路 - 动态获取用户当前操作界面 -> 正文阅读

[移动开发]Android进阶之路 - 动态获取用户当前操作界面

在几个月前有接到项目老大这样一个需求:实时获取用户当前app的操作界面 ~

在早期的时候有记录过一篇关于截图的Blog,有需求也可以去扩展

因为近俩年主要做的是售货机业务,所以长连接使用的是mqtt,这里主要讲接收到消息后,我们去动态获取用户操作界面时的实现方式,即实时截屏+本地保存 ~

局部实现

提要:这里主要实现了单个界面截屏的实现方式,也是较为常见的一种实现方式,不是说不能通过这种方式实现全局截屏,而是使用这种方式后,太多繁琐,所以该方式并不完全适用于全局,但是可以当作借鉴与基础

根据以下操作后,亲测已实现需求功能,但是因售货机版本大多在5.0之前,所以在手机开发时要记得适配 6.0动态权限,7.0文件临时授权

在长连接中收到消息后,我采用eventbus传递消息,进行app当前界面截屏+图片保存

look here:当执行完以选操作时,我们可以去查看本地是否已经保存好我们需要的用户操作界面图 ~

    case Constant.EventBus.SCREEN_SHOT:
    	//截图,mScreenParent为所截图区域的最外层布局控件
        Bitmap bitmap = BitmapTool.convertCanvasViewToBitmap(mScreenParent);
        //图片保存
        if (bitmap != null) {
        	//Constant.LocalPath.BASIC_PATH:Environment.getExternalStorageDirectory().getPath();
            BitmapTool.saveImage(bitmap, Constant.LocalPath.BASIC_PATH);
        }
        break;

mScreenParent控件id,处于layout的最外层
在这里插入图片描述
convertCanvasViewToBitmap - 截图

    /**
     * 创建一个bitmap放于画布之上进行绘制 (简直如有神助)
     */
    public static Bitmap convertCanvasViewToBitmap(View tempView) {
        Bitmap bitmap = Bitmap.createBitmap(tempView.getWidth(),
                tempView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tempView.draw(canvas);
        return bitmap;
    }

saveImage - 保存图片

    /**
     * 保存图片
     */
    public static void saveImage(Bitmap bitmap, String path) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdir();
        }

        try {
            String tmpImgPath = path + "/" + "screenShot" + System.currentTimeMillis() + ".png";
            FileOutputStream fileOutputStream = new FileOutputStream(tmpImgPath);
            int bmSize = bitmap.getByteCount();
            int kb = bmSize / 1024;
            int mb = kb / 1024;
            kb = kb % 1024;
            Log.d("Bitmap", "bitmap size = " + mb + "MB " + kb + "KB");
            //图片压缩
            Bitmap bitmap1 = compressImage(bitmap);
            bitmap1.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
//            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
            bmSize = bitmap1.getByteCount();
            kb = bmSize / 1024;
            mb = kb / 1024;
            kb = kb % 1024;
            Log.d("Bitmap", "bitmap size = " + mb + "MB " + kb + "KB");
//            bitmap.recycle();
            fileOutputStream.close();
        } catch (Exception e) {
            LogTool.e(e.getMessage());
        }
    }

compressImage - 图片压缩

    /**
     * 质量压缩方法
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        int options = 90;
        // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
        while (baos.toByteArray().length / 1024 > 100) {
            // 重置baos即清空baos
            baos.reset();
            // 这里压缩options%,把压缩后的数据存放到baos中
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
            // 每次都减少10
            options -= 10;
            if (options < 0) {
                break;
            }
        }
        // 把压缩后的数据baos存放到ByteArrayInputStream中
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        // 把ByteArrayInputStream数据生成图片
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
        return bitmap;
    }

全局实现

提要:意如其名,通过以下方式,我们可以全局捕获用户的一个实时操作状态,相比上方的话,思维需要更扩展一些

实现思想:因为需要通过activity的维度,进行屏幕截取,所以我们需要一个能实时获取当前activity的管制类,然后在接收到截屏消息后我们将当前activity的实例传入截屏方法中,从而实现全局截屏的功能

根据以下操作后,亲测已实现需求功能,但是因售货机版本大多在5.0之前,所以在手机开发时要记得适配 6.0动态权限,7.0文件临时授权

注意:关于图片最终保存效果,其一取决于手机实际分辨率,其二取决于图片质量压缩时的一个比例

ActivityCollector - activity管理类

package com.nk.machine.base;

import android.app.Activity;

import java.util.ArrayList;
import java.util.List;

/**
 * @author MrLiu
 * @date 2020/4/8
 * desc
 */
public class ActivityCollector {
    public static List<Activity> activities = new ArrayList<>();

    public static void addActivity(Activity activity) {
        activities.add(activity);
    }

    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }

    public static List<Activity> activityList(){
        return activities;
    }

    public static void finishAll() {
        for (Activity activity : activities) {
            if (!activity.isFinishing()) {
                activity.finish();
            }
        }
    }
}

BaseActivity - 需要截屏的activity均继承于BaseActivity,同时配置activity管理类

package com.nk.machine.base;

import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.view.Window;
import android.view.WindowManager;

/**
 * @author MrLiu
 * @date 2020/4/9
 * desc Activity基类
 */
public abstract class BaseActivity extends RxAppCompatActivity {

    private TextView mTitle;
    private ImageView mBack;
    private NkApplication application;
    private ScreenCountTimer screenCountTimer;
    private String className;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }
}

收到截屏消息后,获取当前activity名称,同时从acitivity管理类中,获取当前activity的实例,然后进行屏幕截取与截图保存

    LogTool.e("当前Activity:" + BitmapTool.getRunningActivityName());
    List<Activity> activities = ActivityCollector.activityList();
    String runningActivityName = BitmapTool.getRunningActivityName();
    if (activities.size() > 0) {
        int tmpPosition = 0;
       out: for (int i = 0; i < activities.size(); i++) {
         in: if (runningActivityName.contains(activities.get(i).getLocalClassName())) {
                tmpPosition = i;
                break out;
            }
        }
        Activity activity = activities.get(tmpPosition);
        Bitmap bitmap = BitmapTool.captureNow(activity);
        if (bitmap != null) {
            BitmapTool.saveImage(bitmap, Constant.LocalPath.BASIC_PATH);
        }
    }

getRunningActivityName - 获取当前activity名称

    public static String getRunningActivityName() {
        ActivityManager activityManager = (ActivityManager) NkApplication.getAppContext().getSystemService(Context.ACTIVITY_SERVICE);
        String runningActivity = activityManager.getRunningTasks(1).get(0).topActivity.getClassName();
        return runningActivity;
    }

captureNow - 截取当前activity的屏幕状态

    public static Bitmap captureNow(Activity activity) {
        View view = activity.getWindow().getDecorView();
//        Bitmap bitmap = convertCanvasViewToBitmap(view);
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
//        view.setDrawingCacheEnabled(false);
//        view.destroyDrawingCache();
        if (bitmap != null) {
            return bitmap;
        }
        return null;
    }

saveImage - 保存图片

    /**
     * 保存图片
     */
    public static void saveImage(Bitmap bitmap, String path) {
        File file = new File(path);
        if (!file.exists()) {
            file.mkdir();
        }

        try {
            String tmpImgPath = path + "/" + "screenShot" + System.currentTimeMillis() + ".png";
            FileOutputStream fileOutputStream = new FileOutputStream(tmpImgPath);
            int bmSize = bitmap.getByteCount();
            int kb = bmSize / 1024;
            int mb = kb / 1024;
            kb = kb % 1024;
            Log.d("Bitmap", "bitmap size = " + mb + "MB " + kb + "KB");
            //图片压缩
            Bitmap bitmap1 = compressImage(bitmap);
            bitmap1.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
//            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
            bmSize = bitmap1.getByteCount();
            kb = bmSize / 1024;
            mb = kb / 1024;
            kb = kb % 1024;
            Log.d("Bitmap", "bitmap size = " + mb + "MB " + kb + "KB");
//            bitmap.recycle();
            fileOutputStream.close();
        } catch (Exception e) {
            LogTool.e(e.getMessage());
        }
    }
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-05 17:27:58  更:2021-08-05 17:29:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 11:11:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码