I'm trying to use ADB to open one of the device settings. The setting screen that I want is the one that lists and allows us to add accounts to the device.
For example, adb shell am start -a android.settings.ADD_ACCOUNT_SETTINGS shows the accounts I can add.
I've managed to find that android shows the fragment com.android.settings.accounts.AccountDashboardFragment so tried to:
adb shell am start -n com.android.settings/com.android.settings.SubSettings -e :android:show_fragment com.android.settings.accounts.AccountDashboardFragment
but that throws:
adb shell am start -n com.android.settings/com.android.settings.SubSettings -e :android:show_fragment com.android.settings.accounts.AccountDashboardFragment
Starting: Intent { cmp=com.android.settings/.SubSettings (has extras) }
Exception occurred while executing 'start':
java.lang.SecurityException: Permission Denial: starting Intent { flg=0x10000000 cmp=com.android.settings/.SubSettings (has extras) } from null (pid=24379, uid=2000) not exported from uid 1000
at com.android.server.wm.ActivityStackSupervisor.checkStartAnyActivityPermission(ActivityStackSupervisor.java:1043)
at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:999)
at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:669)
at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1096)
at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1068)
at com.android.server.am.ActivityManagerService.startActivityAsUserWithFeature(ActivityManagerService.java:3662)
at com.android.server.am.ActivityManagerShellCommand.runStartActivity(ActivityManagerShellCommand.java:544)
at com.android.server.am.ActivityManagerShellCommand.onCommand(ActivityManagerShellCommand.java:186)
at android.os.BasicShellCommandHandler.exec(BasicShellCommandHandler.java:98)
at android.os.ShellCommand.exec(ShellCommand.java:44)
at com.android.server.am.ActivityManagerService.onShellCommand(ActivityManagerService.java:10505)
at android.os.Binder.shellCommand(Binder.java:929)
at android.os.Binder.onTransact(Binder.java:813)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:5053)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2867)
at android.os.Binder.execTransactInternal(Binder.java:1159)
at android.os.Binder.execTransact(Binder.java:1123)
Any idea how to bypass this?
I'm trying to trigger an activity using an intent using adb on the command line:
adb shell am start
-a android.intent.action.VIEW
-c android.intent.category.DEFAULT
-t vnd.google.android.package/vnd.google.android.package_something
-n com.google.android.package/com.google.android.apps.package.SomeActivity
but it throws a security exception:
Starting: Intent { act=android.intent.action.VIEW cat=[android.intent.category.DEFAULT] typ=vnd.google.android.package/vnd.google.android.package_something cmp=com.google.android.package/com.google.android.apps.package.SomeActivity }
java.lang.SecurityException: Permission Denial: starting Intent { act=android.intent.action.VIEW cat=[android.intent.category.DEFAULT] typ=vnd.google.android.package/vnd.google.android.package_something flg=0x10000000 cmp=com.google.android.package/com.google.android.apps.package.SomeActivity } from null (pid=31536, uid=2000) requires com.google.android.package.START_ACTIVITY
at android.os.Parcel.readException(Parcel.java:1620)
at android.os.Parcel.readException(Parcel.java:1573)
at android.app.ActivityManagerProxy.startActivityAsUser(ActivityManagerNative.java:2767)
at com.android.commands.am.Am.runStart(Am.java:885)
at com.android.commands.am.Am.onRun(Am.java:361)
at com.android.internal.os.BaseCommand.run(BaseCommand.java:47)
at com.android.commands.am.Am.main(Am.java:101)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:251)
So I tried again with a user who has the missing permission:
adb shell am start
-a android.intent.action.VIEW -c android.intent.category.DEFAULT
-t vnd.google.android.package/vnd.google.android.package_something
-n com.google.android.package/com.google.android.apps.package.SomeActivity
--user 10088
but then it says that the activity doesn't exist:
Starting: Intent { act=android.intent.action.VIEW cat= [android.intent.category.DEFAULT] typ=vnd.google.android.package/vnd.google.android.package_something cmp=com.google.android.package/com.google.android.apps.package.SomeActivity }
Error type 3
Error: Activity class {com.google.android.package/com.google.android.apps.package.SomeActivity} does not exist.
Am I using the user parameter incorrectly? Do I need to include any more information?
You should start activities using the syntax below:
adb shell am start
-n com.google.android.package/.SomeActivity
In your case with user permission:
adb shell am start
-n com.google.android.package/.SomeActivity
--user 10088
I want to debug android's so file. I use start an Activity: am start [-D] [-W] to start activitey.
the applicationg package name is com.dualboot.apps.springzen . the main activity is com.dualboot.apps.springzen.Main$Activity . i use command
'adb shell am start com.dualboot.apps.springzen/com.dualboot.springzen.Main$Actinity'
it's not exist
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.dualboot.apps.springzen/com.dualboot.springzen.Main }
Error type 3
Error: Activity class {com.dualboot.apps.springzen/com.dualboot.springzen.Main} does not exist.
how to start this activity
Since you are calling a component you need to include the component -n option tag.
Use this:
adb shell am start -n com.dualboot.apps.springzen/.MainActivity
if you actually have the $ in your class name (I doubt it) which usually refers to an inner class then you need to use:
adb shell am start -n com.dualboot.apps.springzen/.Main\$Activity
I am trying to start an activity for an app (which I did not write in case you were wondering) through the adb shell. The manifest has the lines:
<activity android:label="#string/app_name" android:name="MainActivity$mainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I have tried using the the commands
adb shell am start -W com.pkg.name/MainActivity$mainActivity
adb shell am start -W com.pkg.name/.MainActivity$mainActivity
adb shell am start -W com.pkg.name/.MainActivity
adb shell am start -a android.intent.action.MAIN -n com.pkg.name/MainActivity$mainActivity
adb shell am start -n com.pkg.name/MainActivity$mainActivity
etc...
and each and every one gives me the error:
Error type 3
Error: Activity class {com.pkg.name/com.pkg.name.MainActivity}
does not exist.
It does however work when clicking on the app icon in the emulator, and by grepping the logcat output I find that the activity being launched is called .MainActivity$mainActivit or .MainActivity, they both show up in the output. Can someone tell me why am start is not working and how to in fact start this activity without manually clicking the icon?
UPDATE: The solution given by laalto is almost right. It turns out it was a problem with the $ getting resolved as an environment variable, however the command he suggested doesn't quite do it. You need to put single quotes around to <pkgname/activityname> in addition to escaping the $.
In unix-like shells, $ is a shell metacharacter so the $mainActivity expands to whatever value the environment variable mainActivity holds, likely an empty value in your case.
To escape it, use a backslash:
adb shell am start -W com.pkg.name/.MainActivity\$mainActivity
However, having an inner class as an entry point is sort of a code smell. Consider making the outer class your entry point. Then you wouldn't need $ in any form.
am start -n com.pkg.name/com.package.name.MainActivity$mainActivity
Good luck
I'm using adb to sync music on an android phone. Essentially, I rm the existing music directory and push replacement music files.
I'd like to be able to use adb to force a rescan, so that the google music player (and other apps) works properly with the new songs and playlists.
According to How can I refresh MediaStore on Android? you can force a rescan by broadcasting an appropriate intent.
adb provides 'shell am broadcast', which would seem to allow me to force a rescan from adb.
Alternatively I could run a rescan app or reboot, but I'd like to trigger the rescan from adb
What adb command should I issue? The music files and playlists are all in /sdcard/music.
The rescan apps use a media mount intent to kick off the media scanner. You can use am broadcast to send the same intent.
The command is:
adb shell am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///sdcard
The MEDIA_MOUNTED intent is no longer permitted (post KitKat) for non-system apps; try this instead.
It’s not recursive, though, and has to be run on the exact_file_name, so it’s not a good replacement.
adb shell am broadcast \
-a android.intent.action.MEDIA_SCANNER_SCAN_FILE \
-d file:///mnt/sdcard/Music/<exact_file_name>
If you need to rescan recursively, you can use this command (fix paths accordingly):
adb shell "find /mnt/sdcard/Music/ -exec am broadcast \
-a android.intent.action.MEDIA_SCANNER_SCAN_FILE \
-d file://{} \\;"
Or like this (if above won't work for you):
adb shell "find /mnt/sdcard/Music/ | while read f; do \
am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE \
-d \"file://${f}\"; done"
On some Samsung mobiles, you can get a full rescan like this:
am broadcast -a com.samsung.intent.action.MTP_FILE_SCAN -n com.android.providers.media/.MediaScannerReceiver
If you have rooted your phone, you can use this script I’ve written, which has the advantage of keeping track of which files have already been updated:
#!/system/bin/env busybox ash
MUSIC_LIBRARY=/sdcard/MusicLibrary
LAST_UPDATE="$(stat -c %Y "$MUSIC_LIBRARY/.last-update")"
find "$MUSIC_LIBRARY" -type f ! -iname ".last-update" | (
while read f; do
if ! test "$LAST_UPDATE" -ge "$(stat -c %Y "$f")"; then
am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d "file://$f"
touch "$f"
else
echo "Not updated: \`$f'"
fi
done
)
touch "$MUSIC_LIBRARY/.last-update"
Here's a Python script called adb-scan.
It uses adb to ask the Android device to rescan the given files.
Example usage:
$ adb-scan Notifications/\*.mp3
Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/Notifications/cough.mp3 flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/Notifications/harmonica3.mp3 flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/Notifications/shhh.mp3 flg=0x400000 }
Broadcast completed: result=0
$
Here's the script:
#!/usr/bin/python3
#
# Ask the Android media scanner to check the given files.
#
import sys
import os
import re
sys.argv.pop(0)
if not sys.argv:
sys.exit('usage: adb-scan files...')
intent = 'android.intent.action.MEDIA_SCANNER_SCAN_FILE'
# Quote certain special characters such as spaces, backslashes and quotes. In
# particular, don't quote '*' because we want that to be expanded on the
# Android device.
def cleanup(arg):
if not arg.startswith('/'):
arg = '/sdcard/' + arg
arg = re.sub("[ \\'\"]", lambda x: '\\' + x.group(0), arg)
return arg
script = '''
for i in {args}; do
[ -e "$i" ] || echo "warning: no such file: $i"
am broadcast -a "{intent}" -d "file://$i"
done
'''.format(args=' '.join(map(cleanup, sys.argv)),
intent=intent)
cmd = ['adb', 'shell', script]
os.execvp(cmd[0], cmd)