模拟在默认系统相机应用程序中拍照

2023-12-25

我正在制作 Android 语音助手应用程序...在后台运行服务以识别语音命令。 当用户说“自拍”这个词时,我想在默认系统相机应用程序中拍照。我已经知道如何使用语音命令,但问题是我无法让相机应用程序拍照......

我尝试了一些方法但没有帮助

第一次我尝试模拟 Android 相机按键事件

Intent intent1 = new Intent("android.intent.action.CAMERA_BUTTON");
intent1.putExtra("android.intent.extra.KEY_EVENT", new KeyEvent(0,
KeyEvent.KEYCODE_CAMERA));
sendOrderedBroadcast(intent1, null);
intent1 = new Intent("android.intent.action.CAMERA_BUTTON");
intent1.putExtra("android.intent.extra.KEY_EVENT", new KeyEvent(1,
KeyEvent.KEYCODE_CAMERA));
sendOrderedBroadcast(intent1, null);

这个可以打开相机,但如果没有物理相机键,就无法在手机中拍照

第二次我尝试注入关键事件“enter”...就像蓝牙远程快门...

    KeyEvent eventDown = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER);
    KeyEvent eventUp = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER);
    dispatchKeyEvent(eventDown);
    dispatchKeyEvent(eventUp);

但在这个问题中,我遇到了两个问题:第一,此代码无法在服务中使用;第二,不可能将事件注入到其他应用程序,因为只有系统应用程序可以执行此操作

现在的问题是我该如何解决这个问题? 可能吗? 我在网上读到一些内容,说 appium 可以做到这一点,但它是在线的,我希望我的应用程序离线工作

注意:添加相机权限和注入事件权限不会有帮助,我不想使用相机 API,因为我想在默认系统相机应用程序中拍照。


是的,有可能经过两天的调查,我找到了解决方案。

要求:打开系统相机应用程序并单击图片。

Step 1:

在清单文件中添加相机权限:

<uses-permission android:name="android.permission.CAMERA"/>

<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera.front"
    android:required="false" />

Step 2:创建一项可扩展的服务无障碍服务

    <service
        android:name=".AccessTest"
        android:enabled="true"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
        android:exported="true">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService" />
        </intent-filter>

        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/accessibility_service_config"/>
    </service>

Step 3:当您需要时开始服务

    Intent mailAccessabilityIntent = new Intent(getApplicationContext(), AccessTest.class);
    startService(mailAccessabilityIntent);

Step 4:添加辅助功能文件。

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:accessibilityFlags="flagEnableAccessibilityVolume"
    android:canRetrieveWindowContent="true"
    android:notificationTimeout="100"
    android:packageNames="com.google.android.GoogleCamera"
    android:settingsActivity="com.mobiliya.cameraautoclick.MainActivity" />

Step 5:在要处理与相机相关的侦听器的位置编写服务类。

public class AccessTest extends AccessibilityService {

    private final static String TAG = "Yogesh";


    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("Yogesh","I am started");
    }

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.d(TAG, "onServiceConnected");
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
      Log.d(TAG, "ACC::onAccessibilityEvent: " + event.getEventType());

        //TYPE_WINDOW_STATE_CHANGED == 32
        if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event
                .getEventType()) {
            AccessibilityNodeInfo nodeInfo = event.getSource();

            if (nodeInfo == null) {
                return;
            }


            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

            String x = takePictureIntent.resolveActivity(getPackageManager()).getPackageName();

            Log.d("Yogesh","Package name " + x);

            List<AccessibilityNodeInfo> list1 = nodeInfo.findAccessibilityNodeInfosByText("Switch to front camera");

            for (AccessibilityNodeInfo node : list1) {
                Log.i(TAG, "ACC::onAccessibilityEvent: click " + node);
                node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }

            final List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText("Take photo");


            final android.os.Handler handler = new android.os.Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {

                    for (AccessibilityNodeInfo node : list) {
                        Log.i(TAG, "ACC::onAccessibilityEvent: click " + node);
                        node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                    handler.postDelayed(this,5000);
                }
            },10000);

            for (AccessibilityNodeInfo node : list) {
                Log.i(TAG, "ACC::onAccessibilityEvent: click " + node);
                node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }

            Log.d(TAG,"Access " + getAllChildNodeText(nodeInfo).toString());
        }
    }



    private List<CharSequence> getAllChildNodeText(AccessibilityNodeInfo infoCompat) {
        List<CharSequence> contents = new ArrayList<>();
        if (infoCompat == null)
            return contents;
        if (infoCompat.getContentDescription() != null) {
            contents.add(infoCompat.getContentDescription().toString().isEmpty() ? "unlabelled" : infoCompat.getContentDescription());
        } else if (infoCompat.getText() != null) {
            contents.add(infoCompat.getText().toString().isEmpty() ? "unlabelled" : infoCompat.getText());
        } else {
            getTextInChildren(infoCompat, contents);
        }
        if (infoCompat.isClickable()) {
            if (infoCompat.getClassName().toString().contains(Button.class.getSimpleName())) {
                if (contents.size() == 0) {
                    contents.add("Unlabelled button");
                } else {
                    contents.add("button");
                }
            }
            contents.add("Double tap to activate");
        }
        return contents;
    }


    private void getTextInChildren(AccessibilityNodeInfo nodeInfoCompat, List<CharSequence> contents) {
        if (nodeInfoCompat == null)
            return;
        if (!nodeInfoCompat.isScrollable()) {
            if (nodeInfoCompat.getContentDescription() != null) {
                contents.add(nodeInfoCompat.getContentDescription());
            } else if (nodeInfoCompat.getText() != null) {
                contents.add(nodeInfoCompat.getText());
            }
            if (nodeInfoCompat.getChildCount() > 0) {
                for (int i = 0; i < nodeInfoCompat.getChildCount(); i++) {
                    if (nodeInfoCompat.getChild(i) != null) {
                        getTextInChildren(nodeInfoCompat.getChild(i), contents);
                    }
                }
            }
        }
    }



    @Override
    public void onInterrupt() {

    }
}

Here getAllChildNodeText()返回所有可点击的文本按钮,Google默认应用程序有Take Photo文本,以便您可以在此视图中执行操作。

Added handler每 10 秒捕获一次图片以获得更多说明。

如果您想跟踪多个摄像头应用程序,请删除以下行并使用 Java 代码设置包更多详细信息请参阅 -无障碍服务 https://developer.android.com/reference/android/accessibilityservice/AccessibilityService

android:packageNames="com.google.android.GoogleCamera"

我上传了工作示例 -> https://github.com/ycrathi/cameraautoclick https://github.com/ycrathi/cameraautoclick

注意:上面的 GitHub 存储库中有多个不需要的代码,我尝试过。

该解决方案不适用于所有应用程序。您可以找到一些著名的应用程序,例如谷歌相机找到文本,然后明智地执行单击操作包。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模拟在默认系统相机应用程序中拍照 的相关文章

随机推荐

  • Javascript URL 深度(级别)

    是否可以使用 Javascript 获取 url 深度 级别 如果我有这个网址 www website com site product category item gt 深度 4 www website com site product
  • Spring Security 中的 beans.NotReadablePropertyException

    我对 Spring Security 非常陌生 我捡起来了this https rads stackoverflow com amzn click com 1847199747书并尝试执行代码 当我这样做时 我得到了 org springf
  • 如何读取 Objective-C 堆栈跟踪

    我有以下堆栈跟踪 0 MyApp 0x000833a3 TFCrashHandler backtrace 26 1 MyApp 0x000836bd TFSignalHandler 28 2 libsystem c dylib 0x33ea
  • 删除重复行并更新引用

    如何删除一个表中的重复行并将另一表中的引用更新为剩余行 重复仅出现在名称中 Id 列是标识列 Example 假设我们有两张表Doubles and Data Doubles table Id int Name varchar 50 Dat
  • 如何从嵌入式 HTML 与 Swift 进行通信以更改 bool

    您好 我想在执行 html 中的 onReady 块后更改绑定变量 click 的值 我可以使用评估java脚本从swift到html进行通信 但是我如何从 html 中的 onReady 与 swift 进行通信以更改 bools val
  • Chrome 扩展中的跨源 XMLHttpRequest

    根据 chrome 扩展 API 如果设置了权限 则应允许使用 XMLHttpRequest 对象进行跨源调用 只要扩展程序首先请求跨源权限 就可以与其源之外的远程服务器进行通信 我正在密切关注谷歌教程 http code google c
  • 如何 dplyr 按列索引重命名列?

    以下代码重命名数据集中的第一列 require dplyr mtcars gt setNames c RenamedColumn names 2 length names 期望的结果 RenamedColumn cyl disp hp dr
  • jsPlumb:如何选择特定连接器

    我似乎不知道如何选择特定的 jsPlumb 连接器 我知道我可以选择与源或目标相关的所有连接器 但通常我会在同一源和目标之间有多个连接器 因此在这种情况下我看不到能够选择特定连接器的方法 我的具体用例如下 如果用户单击连接器 则会出现一个对
  • 无法重新启动 Spring 批处理作业

    我有一个 Spring Batch 作业 用于读取 转换和写入 Oracle 数据库 我通过 CommandLineJobRunner 实用程序运行该作业 使用 fat jar 使用 Maven Shade 插件生成的依赖项 该作业随后由于
  • 有没有办法在 JavaScript 中清除对象?

    有没有办法清除 Javascript 中的对象 具体来说 如果一个对象有多个成员变量 是否有一种简单的方法来重置每个值 function exampleObject this valueA A this valueB B this myAr
  • SQL——在 select 语句中分配位变量

    例如 declare bitHaveRows bit select bitHaveRows count from table where predicate 我可以在这一行调用任何函数吗 select bitHaveRows count 如
  • 如何在请求写入代理 Netty 服务器中的 outboundChannel 时在同一处理程序中获取响应 byteBuf

    我正在实现 netty 代理服务器 如下所示 一个http请求进来 如果本地缓存有数据 则写入channel并flush 如果没有 则从远程服务器获取数据 将其添加到缓存并刷新 我在与写入客户端的处理程序相同的处理程序中从响应中提取 byt
  • 如何查找Javascript语法错误? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在编写一段 JavaScript 代码 并在语法中犯了很多愚蠢的错误 但是找到错误所在行的唯一方法是开始注释掉我刚刚编写的代码部分
  • 搜索 R-Studio 中所有打开的文件

    R Studio 中的普通搜索功能 ctrl f 仅搜索当前选定的文件 有没有办法搜索所有打开的文件 Tom 查看以下文档 http www rstudio com ide docs using navigation http www rs
  • 我需要在共享内存对象上使用 shm_unlink 吗?

    我编写了一个连续运行的服务器 GNU C Linux 偶尔执行小型独立程序来完成工作 为了有效地将数据获取到工作程序 服务器创建并映射一个共享内存对象 为了清楚起见 缩写了代码 int fd shm open shm file O CREA
  • 如何在MaterialDesignInXamlToolkit中添加个人图标?

    Material Design Icons 项目包含大量图标 但对于非英语国家来说还不够 那么如何在不修改源代码的情况下在个人项目中添加另一个包图标呢 正如 mm8所说 是的 这只是一条路径 但是 是的 您可以构建自己的 PackIcon
  • Android Afreechart - 更改点形状、线条粗细和颜色

    我正在尝试在我的应用程序中更改折线图点的形状 我在用afreechart s TimeSeriesChart 我想让这条线在粗细 颜色和点形状方面变得更漂亮 哪里可以改代码 将使用哪种方法 我现在拥有的 source googlecode
  • 通过 ckeditor 上传的 django+heroku+S3 图片在创建帖子一段时间后被删除

    我已经在heroku中部署了我的django应用程序 postgresql作为数据库并用于存储我使用亚马逊S3存储的图像 我面临的问题是 用于创建我使用过的博客文章 ckeditor 因此用户可以输入图像以及内容文本来创建帖子 创建帖子后
  • 由于“找不到符号类 X”错误,无法在 Intellij Idea 中编译 java 类

    我在项目中从头开始创建了新的 Java 模块 在模块创建向导中选择了 创建 src 文件夹 源文件夹中有一个 com 包 其中包含两个公共类 例如 A 和 B A类实例化B类 IDE 不显示错误 并且当光标位于 A 类源内的类名上时 按 c
  • 模拟在默认系统相机应用程序中拍照

    我正在制作 Android 语音助手应用程序 在后台运行服务以识别语音命令 当用户说 自拍 这个词时 我想在默认系统相机应用程序中拍照 我已经知道如何使用语音命令 但问题是我无法让相机应用程序拍照 我尝试了一些方法但没有帮助 第一次我尝试模