【问题标题】:Android Notifications through ADB通过 ADB 的 Android 通知
【发布时间】:2021-12-22 03:30:30
【问题描述】:

我正在编写一个 shell 脚本,它允许您在使用 Terminal 并行连接到计算机的所有 Android 手机上安装 .apk。在我的公司,我们在许多设备上进行测试,因此这使得安装部分必须更快。

问题:我正在寻找一种方法来通过某种反馈/通知快速识别哪些手机安装了 .apk。理想情况下,您应该能够通过查看它(某种声音或屏幕闪烁)或简单地解锁设备(例如,新安装的应用程序已打开)来查看哪些手机收到了 .apk。

对我可以如何做这些事情有任何想法吗?

我已阅读有关启动应用程序的信息,但似乎仅使用 .apk 无法做到这一点(您还需要指定一个活动......)。

任何想法将不胜感激!

谢谢!

【问题讨论】:

    标签: android shell automation adb


    【解决方案1】:

    找到了我自己的解决方案!

    我正在使用:

    aapt dump badging
    

    认为这只会输出包名。事实证明它输出了更多有用的信息。我注意到的其中一行是输出是应用程序的启动活动。我能够用 grep 隔离这条线,然后像这样切断启动活动:

    aapt dump badging $1 | grep launchable | cut -d "'" -f 2
    

    如果您知道某个应用的活动,则有一个命令可让您启动应用。添加此行会启动使用上述命令检索到的活动。

    adb -s $deviceID shell am start -a android.intent.action.MAIN -n $packageName/$launchableActivity
    

    我在安装命令之后将这一行放在我的 for 循环中。不安装应用程序后,脚本将尝试在之后启动它。非常便利!

    感谢大家的帮助! :D

    【讨论】:

      【解决方案2】:

      使用包管理器检查 APK 是否安装:

      pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [FILTER]
      
      pm list packages: prints all packages, optionally only
        those whose package name contains the text in FILTER.  Options:
          -f: see their associated file.
          -d: filter to only show disbled packages.
          -e: filter to only show enabled packages.
          -s: filter to only show system packages.
          -3: filter to only show third party packages.
          -i: see the installer for the packages.
          -u: also include uninstalled packages.
      

      例如

      $ adb shell pm list packages com.example.mypkg
      

      【讨论】:

        【解决方案3】:

        您可以使用带有参数的“adb shell am start”来启动新安装的包。

        如果担心不会被旧的混淆,请在安装新的之前先卸载旧的,或者最好让您的启动活动显示版本控制。

        您实际上可以使用 am start 启动启动器不知道的活动,因此您可以使用它直接启动“关于”活动,该活动将显示当前版本。您的选择是在应用程序的普通过程中提供它,还是仅使用一次作为启动。

        您还应该能够解析 adb install 命令的输出 - 您必须查看它是否将错误/成功发送到 stderr 或 stdout。

        更新:以下是创建一个可用于打开屏幕并显示消息的 Activity 的方法,如下所示:

        adb shell 'am start -n com.example.testreport/.ReportActivity -e result PASS'
        

        代码大量抄袭自早期安卓版本的内置闹钟,需要:

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

        在清单中

        package com.example.testreport;
        import android.app.Activity;
        import android.content.Context;
        import android.content.Intent;
        import android.os.Bundle;
        import android.os.PowerManager;
        import android.util.Log;
        import android.view.Gravity;
        import android.view.WindowManager;
        import android.view.WindowManager.LayoutParams;
        import android.widget.TextView;
        public class ReportActivity extends Activity {
            PowerManager.WakeLock sScreenWakeLock;
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                 requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
                 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
            }
            protected void onStart() {
                super.onStart();
        
                if (sScreenWakeLock == null) {
                    PowerManager pm =
                            (PowerManager) getSystemService(Context.POWER_SERVICE);
                    sScreenWakeLock = pm.newWakeLock(
                            PowerManager.FULL_WAKE_LOCK |
                            PowerManager.ACQUIRE_CAUSES_WAKEUP |
                            PowerManager.ON_AFTER_RELEASE, "ReportActivity Wakelock");
                    sScreenWakeLock.acquire();
                }
                TextView tv=new TextView(this);
                tv.setTextSize(30);
                tv.setGravity(Gravity.CENTER);
                Intent i = getIntent();
                if ((i != null) && (i.hasExtra("result"))) 
                    tv.setText(i.getStringExtra("result"));
                else 
                    tv.setText("???");
                setContentView(tv);
            }
            protected void onStop() {
                if (sScreenWakeLock != null) {
                    sScreenWakeLock.release();
                    sScreenWakeLock = null;
                }
                super.onStop();
            }
        }
        

        它可能需要一些清理和改进;例如,目前您无法使用电源按钮关闭手机,除非您首先通过导航使其失去可见性来停止活动。

        【讨论】:

        • 感谢您的回答!实际上,我已经将其设置为将设备 ID 与每个失败/成功输出相关联,并且脚本会在最后打印出失败/完成的设备。问题是很难从 ID 中识别某些设备。如果所有完成的都发出哔哔声,那就更容易了。或者我可以使用 ID 获取真实的设备名称吗?再次感谢! @dtmilano
        • 非常感谢您的帮助!不幸的是,我无法控制进入应用程序的代码,但这真的很整洁!实际上,我自己设法找到了一个解决方案,如果您有兴趣,我将在下面发布。再次感谢!
        • 这可以放在它自己的应用程序中,它只是 adb 用来在设备上直观地报告信息的工具。你想到了什么?
        • 在我回答自己的帖子之前必须等待 8 小时:P。现在在下面。再次感谢!
        【解决方案4】:

        我可以看到这样做的一种方法是验证应用程序安装的应用程序。特别是应在设备上安装的应用程序清单,并且在 PackageManager 完成安装时,它会根据此广播进行更新。

        除了在 App 层之外进行之外,我认为这是不可能的,除非你嗅探到设备的 USB 端口并识别命令和有效负载并弄清楚(HACK)强>

        【讨论】:

          【解决方案5】:

          你可以通过运行检查包是否安装

          adb shell pm list packages your-package-name-here
          

          如果已安装,它将返回 package:your-package-name-here,因此您可以将返回值存储在变量中,然后检查该变量是否为 null 或“package:your-package-name-here”。

          要在设备上打开已安装的应用,即使您没有要调用的任何特定活动,也可以运行

          adb shell monkey -p your-package-name-here -c android.intent.category.LAUNCHER 1
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-03-21
            • 2016-01-13
            • 2016-12-19
            • 1970-01-01
            • 2015-01-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多