7

I'm writing a shell script that allows you to install an .apk on all android phones connected to a computer in parallel using Terminal. At my company we do tests on many devices and so this makes the installation part must faster.

Question: I'm looking for a way to quickly identify which phones have had the .apk installed via some sort of feedback/notification. Ideally you should be able to see which phones have received the .apk just by looking at it (some sort of sound or screen flash) or simply by unlocking the device (ex. the newly installed app has been opened).

Any ideas of how I could do either of these things?

I've read about launching apps but it seems like thats not something you could do with just the .apk (you would also need to specify an activity...).

Any ideas would be much appreciated!

Thanks!

HaroldT
  • 131
  • 1
  • 1
  • 7

5 Answers5

6

Found my own solution!

I was using:

aapt dump badging

thinking that this would just output the package name. Turns out it outputs a lot more of useful info. One of the lines I noticed was output is the launch activity of the app. I was able to isolate this line with grep and then cut out the launch activity as so:

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

Then there is a command that allows you to launch an app if you know one of it's activities. Adding this line launches the activity that was retrieved using the above command.

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

I placed this line in my for loop right after the install command. No after the app is installed the script will attempt to launch it afterwards. Very handy!

Thanks for all the help! :D

HaroldT
  • 131
  • 1
  • 1
  • 7
3

Use the package manager to check if the APK is installed:

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.

for example

$ adb shell pm list packages com.example.mypkg
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
1

You can use the 'adb shell am start' with arguments you will need to look up to start your newly installed package.

If there's any concern about not being confused by a stale one, adb uninstall the old one before installing the new one, or better yet have your splash activity display versioning.

You can actually use am start to launch an activity which isn't known to the launcher, so you could use it to launch directly to an "about" activity which would display the current version. Your choice if you make that available in the ordinary course of the application, or only use it this one time as a splash.

You should also be able to parse the output of the adb install command - you'll have to see if it sends errors / success to stderr or stdout.

UPDATE: Here's how to make an activity which you can use to turn the screen on and display a message, like this:

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

The code is heavily cribbed from the built in AlarmClock of an early android version, it will require:

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

in the manifest

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();
    }
}

It can probably use some cleanup and improvement; for example at the moment you can't turn the phone off with the power button unless you first stop the activity by navigating away to make it lose visibility.

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117
  • Thanks for the answers! I've actually already got it setup to associate device IDs with each Fail/Success output and the script prints out the devices that failed/completed at the end. The problem is that it's hard to identify some devices from their ID. If all the completed ones were beeping that would make it easier. Or could I grab real device names using the IDs? Thanks again! @dtmilano – HaroldT Jul 06 '12 at 04:54
  • Thanks so much for your help! Unfortunately I don't have control over the code that goes into the apps, but this is really neat! I actually managed to find a solution myself which I will post below if you are interested. Thanks again! – HaroldT Jul 06 '12 at 06:07
  • This could go in its own app, its just a tool for adb to use to report information visually on a device. What did you come up with? – Chris Stratton Jul 06 '12 at 06:09
  • Had to wait 8 hours before I answered my own post :P. It's below now. Thanks again! – HaroldT Jul 09 '12 at 15:38
0

One way i could see this being done is an application that verifies the installation of the applications. Specifically a checklist of applications that should be installed on the device and as the PackageManager finishes the installation, it updates based on this broadcast.

Aside from doing it outside of the App layer, I don't think its possible unless you sniff the USB port that is going to the device and identify the commands and payload and figure that out (HACK)

JoxTraex
  • 13,423
  • 6
  • 32
  • 45
0

You could check if the package is installed by running

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

That would return package:your-package-name-here if it's installed, so you could store the return value in a variable and then check if the variable is null or "package:your-package-name-here".

To open up your installed app on the device even if you don't have any specific activity to call, you can run

adb shell monkey -p your-package-name-here -c android.intent.category.LAUNCHER 1
Naftoli Ost
  • 91
  • 1
  • 5