I've got BroadcastReceiver class:
public class IntentReceiver extends BroadcastReceiver {
final String tag = "Intent Intercepter";
#Override
public void onReceive(Context context, Intent intent) {
try {
String data = intent.getStringExtra("sms_body");
Log.i(tag, data);
Toast.makeText(context, data.subSequence(0, data.length()), Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(context, "Intercepted", Toast.LENGTH_LONG).show();
}
}
}
And also in manifest:
<receiver android:name="com.whereismywifeserver.IntentReceiver" android:enabled="true">
<intent-filter android:priority="999">
<action android:name="com.whereismywifeserver.intent.TEST"/>
</intent-filter>
</receiver>
But when I try to send intent from adb, I receive error:
$ adb shell am start
-a com.whereismywifeserver.intent.TEST
--es sms_body "test from adb"
-c android.intent.category.HOME
-n com.whereismywifeserver/.IntentReceiver
Starting: Intent { act=com.whereismywifeserver.intent.TEST t=[android.intent.category.HOME] cmp=com.whereismywifeserver/.IntentReceiver (has extras) }
Error type 3
Error: Activity class {com.whereismywifeserver/com.whereismywifeserver.IntentReceiver} does not exist.
When I create intent in code, everything works fine. So how can I send intent from adb?
You need not specify receiver. You can use adb instead.
adb shell am broadcast -a com.whereismywifeserver.intent.TEST
--es sms_body "test from adb"
For more arguments such as integer extras, see the documentation.
The true way to send a broadcast from ADB command is :
adb shell am broadcast -a com.whereismywifeserver.intent.TEST --es sms_body "test from adb"
And, -a means ACTION, --es means to send a String extra.
PS. There are other data type you can send by specifying different params like:
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--esn <EXTRA_KEY> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]
[--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]
[--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]
[--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]
[--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]
(mutiple extras passed as Integer[])
[--eial <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]
(mutiple extras passed as List<Integer>)
[--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]
(mutiple extras passed as Long[])
[--elal <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]
(mutiple extras passed as List<Long>)
[--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]
(mutiple extras passed as Float[])
[--efal <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]
(mutiple extras passed as List<Float>)
[--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]
(mutiple extras passed as String[]; to embed a comma into a string,
escape it using "\,")
[--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]
(mutiple extras passed as List<String>; to embed a comma into a string,
escape it using "\,")
[-f <FLAG>]
For example, you can send an int value by:
--ei int_key 0
I've found that the command was wrong, correct command contains "broadcast" instead of "start":
adb shell am broadcast -a com.whereismywifeserver.intent.TEST --es sms_body "test from adb" -n com.whereismywifeserver/.IntentReceiver
As many already noticed, the problem manifests itself only if the extra string contains whitespaces.
The root cause is that OP's host OS/shell (i.e. Windows/cmd.exe) mangles the entered command - the " characters get lost, --es sms_body "test from adb" becomes --es sms_body test from adb. Which results in sms_body string extra getting assigned the value of test and the rest of the string becoming <URI>|<PACKAGE>|<COMPONENT> specifier.
To avoid all that you could use:
adb shell "am broadcast -a com.whereismywifeserver.intent.TEST --es sms_body 'test from adb' -n com.whereismywifeserver/.IntentReceiver"
or just start the interactive adb shell session first and run the am broadcast command from inside of it.
Another thing to keep in mind: Android 8 limits the receivers that can be registered via manifest (e.g., statically)
https://developer.android.com/guide/components/broadcast-exceptions
Using Android 8 and above with added implicit receivers restrictions, you should add a package name of your app at the end of a terminal command:
adb shell am broadcast -a my.app.package.TEST my.app.package
In case if you have a suffix in debug mode for your package, use my.app.package.debug instead.
Noting down my situation here may be useful to somebody,
I have to send a custom intent with multiple intent extras to a broadcast receiver in Android P,
The details are,
Receiver name: com.hardian.testservice.TestBroadcastReceiver
Intent action = "com.hardian.testservice.ADD_DATA"
intent extras are,
"text"="test msg",
"source"= 1,
Run the following in command line.
adb shell "am broadcast -a com.hardian.testservice.ADD_DATA --es text 'test msg' --es source 1 -n com.hardian.testservice/.TestBroadcastReceiver"
Hope this helps.
I had the same problem and found out that you have to escape spaces in the extra:
adb shell am broadcast -a com.whereismywifeserver.intent.TEST --es sms_body "test\ from\ adb"
So instead of "test from adb" it should be "test\ from\ adb"
I am not sure whether anyone faced issues with getting the whole string "test from adb". Using the escape character in front of the space worked for me.
adb shell am broadcast -a com.whereismywifeserver.intent.TEST --es sms_body "test\ from\ adb" -n com.whereismywifeserver/.IntentReceiver
Related
I'm running Linux Mint, and the device connected is a ZTE HSUSB, which runs on Android v4.1.2.
The screen re-sizing command seems to work: I executed adb shell am display-size 640x480 and it correctly resized the screen.
However, when I tried to adjust the screen density with adb shell am display-density 160 I got
administrator-LenovoPC ~ # adb shell am display-density 160
usage: am [subcommand] [options]
usage: am start [-D] [-W] [-P <FILE>] [--start-profiler <FILE>]
[--R COUNT] [-S] [--opengl-trace] <INTENT>
am startservice <INTENT>
am force-stop <PACKAGE>
am kill <PACKAGE>
am kill-all
am broadcast <INTENT>
am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]
[--no-window-animation] <COMPONENT>
am profile start <PROCESS> <FILE>
am profile stop [<PROCESS>]
am dumpheap [flags] <PROCESS> <FILE>
am set-debug-app [-w] [--persistent] <PACKAGE>
am clear-debug-app
am monitor [--gdb <port>]
am screen-compat [on|off] <PACKAGE>
am display-size [reset|MxN]
am to-uri [INTENT]
am to-intent-uri [INTENT]
am start: start an Activity. Options are:
-D: enable debugging
-W: wait for launch to complete
--start-profiler <FILE>: start profiler and send results to <FILE>
-P <FILE>: like above, but profiling stops when app goes idle
-R: repeat the activity launch <COUNT> times. Prior to each repeat,
the top activity will be finished.
-S: force stop the target app before starting the activity
--opengl-trace: enable tracing of OpenGL functions
am startservice: start a Service.
am force-stop: force stop everything associated with <PACKAGE>.
am kill: Kill all processes associated with <PACKAGE>. Only kills.
processes that are safe to kill -- that is, will not impact the user
experience.
am kill-all: Kill all background processes.
am broadcast: send a broadcast Intent.
am instrument: start an Instrumentation. Typically this target <COMPONENT>
is the form <TEST_PACKAGE>/<RUNNER_CLASS>. Options are:
-r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with
[-e perf true] to generate raw output for performance measurements.
-e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a
common form is [-e <testrunner_flag> <value>[,<value>...]].
-p <FILE>: write profiling data to <FILE>
-w: wait for instrumentation to finish before returning. Required for
test runners.
--no-window-animation: turn off window animations will running.
am profile: start and stop profiler on a process.
am dumpheap: dump the heap of a process. Options are:
-n: dump native heap instead of managed heap
am set-debug-app: set application <PACKAGE> to debug. Options are:
-w: wait for debugger when application starts
--persistent: retain this value
am clear-debug-app: clear the previously set-debug-app.
am monitor: start monitoring for crashes or ANRs.
--gdb: start gdbserv on the given port at crash/ANR
am screen-compat: control screen compatibility mode of <PACKAGE>.
am display-size: override display size.
am to-uri: print the given Intent specification as a URI.
am to-intent-uri: print the given Intent specification as an intent: URI.
<INTENT> specifications include these flags and arguments:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--esn <EXTRA_KEY> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]
[--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]
[--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]
[--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]
[--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]
[--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]
[--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]
[-n <COMPONENT>] [-f <FLAGS>]
[--grant-read-uri-permission] [--grant-write-uri-permission]
[--debug-log-resolution] [--exclude-stopped-packages]
[--include-stopped-packages]
[--activity-brought-to-front] [--activity-clear-top]
[--activity-clear-when-task-reset] [--activity-exclude-from-recents]
[--activity-launched-from-history] [--activity-multiple-task]
[--activity-no-animation] [--activity-no-history]
[--activity-no-user-action] [--activity-previous-is-top]
[--activity-reorder-to-front] [--activity-reset-task-if-needed]
[--activity-single-top] [--activity-clear-task]
[--activity-task-on-home]
[--receiver-registered-only] [--receiver-replace-pending]
[--selector]
[<URI> | <PACKAGE> | <COMPONENT>]
Error: Unknown command: display-density
Does anybody know the reason to this, and how to possibly fix it?
Is it possible to start an Android application with different parameters (e.g. boolean or int type) from command prompt and how I can catch these parameters in my activity class? What is the best way to do that?
I want start application this way but with parameters which I can using in code:
adb shell am start -a android.intent.action.MAIN -n com.XXX.xxx/com.XXX.xxx.Main
Thank in advance.
You can use the following parameters:
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--esn <EXTRA_KEY> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]
[--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]
[--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]
[--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]
For example:
adb shell am start -a android.intent.action.MAIN -n com.XXX.xxx/com.XXX.xxx.Main --es STRING_PAR_NAME stringParameterValue
They are accessible from the Intent, used to start activity, via get[Type]Extra() - e.g. getStringExtra(String name). You can get it using getIntent() if activity was just launched or in Intent parameter in onNewIntent(Intent intent) if activity is already running.
I found this script to test Google Campaign Parameters received:
adb shell am broadcast -a com.android.vending.INSTALL_REFERRER -n com.accuweather.android/com.accuweather.android.services.GoogleCampaignTrackingReceiver --es "referrer" "utm_source=test_androidlite_source&utm_medium=test_medium&utm_term=test_term&utm_content=test_content&utm_campaign=test_name"
Found here
Here is how I am receiving it for testing purposes:
public class GoogleCampaignTrackingReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String referrerString = extras.getString("referrer");
Logger.i(this, "referrer string is %s", referrerString);
}
}
And I am wondering how I get all the parameters, not just the first? Here is the log statement:
03-13 18:40:41.990: I/GoogleCampaignTrackingReceiver(30212): referrer string is utm_source=test_androidlite_source
I'm faced same issue and spend couple hours to find the answer.
In my case, i send broadcast
./adb shell am broadcast -a com.android.vending.INSTALL_REFERRER --es
"referrer"
"traffic=test1&md=1t1&utm_source=test1&utm_medium=android&utm_campaign=test12&utm_term=t3&utm_content=t5
And got only first param
Solution is simple - you need enter the adb shell first
./adb shell
And then send your broadcast
shell#android:/ $ am broadcast -a com.android.vending.INSTALL_REFERRER --es
"referrer"
"traffic=test1&md=1t1&utm_source=test1&utm_medium=android&utm_campaign=test12&utm_term=t3&utm_content=t5
All params will be received correctly.
I hope it will be useful, since i have not find such explanations
Ideally, to open the default browser and navigate to Google Maps (for Taipei 101), you can simply execute:
startActivity(action='android.intent.action.VIEW', data='http://maps.google.com/?q=25.033611,121.565000&z=19')
However, the statement doens't (always) work. After tracing monkeyrunner's source codes:
http://androidxref.com/source/xref/sdk/monkeyrunner/src/com/android/monkeyrunner/MonkeyDevice.java#startActivity
http://androidxref.com/source/xref/sdk/chimpchat/src/com/android/chimpchat/adb/AdbChimpDevice.java#startActivity
Here is a snippet that shows that internally monkeyrunner simply concatenate parameters literally. Please focus on #388 and #411
383 public void startActivity(String uri, String action, String data, String mimetype,
384 Collection<String> categories, Map<String, Object> extras, String component,
385 int flags) {
386 List<String> intentArgs = buildIntentArgString(uri, action, data, mimetype, categories,
387 extras, component, flags);
388 shell(Lists.asList("am", "start",
389 intentArgs.toArray(ZERO_LENGTH_STRING_ARRAY)).toArray(ZERO_LENGTH_STRING_ARRAY));
390 }
...
406 private List<String> buildIntentArgString(String uri, String action, String data, String mimetype,
407 Collection<String> categories, Map<String, Object> extras, String component,
408 int flags) {
409 List<String> parts = Lists.newArrayList();
410
411 // from adb docs:
412 //<INTENT> specifications include these flags:
413 // [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
414 // [-c <CATEGORY> [-c <CATEGORY>] ...]
415 // [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
416 // [--esn <EXTRA_KEY> ...]
417 // [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
418 // [-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
419 // [-n <COMPONENT>] [-f <FLAGS>]
420 // [<URI>]
421
422 if (!isNullOrEmpty(action)) {
423 parts.add("-a");
424 parts.add(action);
425 }
426
427 if (!isNullOrEmpty(data)) {
428 parts.add("-d");
429 parts.add(data);
430 }
...
479 return parts;
480 }
For this case, the following shell command will be executed.
$ am start -a android.intent.action.VIEW -d http://maps.google.com/?q=25.033611,121.565000&z=19
$ Starting: Intent { act=android.intent.action.VIEW dat=http://maps.google.com/?q=25.033611,121.565000 }
[1] Done am start -a android.intent.action.VIEW -d http://maps.google.com/?q=25.033611,121.565000
You may find that the root cause is the ampersand (&). It is interpreted specially in the shell enviroment, that is executing preceding command in the background.
To avoid this misinterpretation, we can escape that special character by prefixing \ to it.
$ am start -a android.intent.action.VIEW -d http://maps.google.com/?q=25.033611,121.565000\&z=19
Starting: Intent { act=android.intent.action.VIEW dat=http://maps.google.com/?q=25.033611,121.565000&z=19 }
Therefore, in monkeyrunner, you should escape parameter values before passing them into startActivity (or even other MonkeyDevice methods), to circumvent this problem.
startActivity(action='android.intent.action.VIEW', data=r'http://maps.google.com/?q=25.033611,121.565000\&z=19')
Finally, it works!! However, I think monkeyrunner, as a friendly API, should do this escaping internally. How do you think?
Yes, you are absolutely right. The way I found of circumventing this an other nuisances is to use
device.shell('am start ...')
where at least you know what to expect.
I'm working with the latest version of android maven plugin. I use android:deploy and android:run to launch my app on my device. When I want to debug, I go into DDMS in eclipse and check the green bug icon for my app. Everything works fine... but I can only debug a running app, ie it has already started. If I put a breakpoint in my application constructor or onCreate, it wont stop (obviously because the application has started and the debugging didn't been activated... yet).
So my question is: how can I start my app in debug mode directly from maven like I would do for an app that I start from eclipse ?
thanks ahead
Thanks to Lukasz, I found the command in Idea that is launched to trigger the debug mode.
Basically, the application is deployed with android:deploy but instead of android:run, I launch a shell "am" command with -D. Here's the usage for anyone interested.
ovh-ybi$ adb shell
# am
usage: am [subcommand] [options]
start an Activity: am start [-D] <INTENT>
-D: enable debugging
send a broadcast Intent: am broadcast <INTENT>
start an Instrumentation: am instrument [flags] <COMPONENT>
-r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT)
-e <NAME> <VALUE>: set argument <NAME> to <VALUE>
-p <FILE>: write profiling data to <FILE>
-w: wait for instrumentation to finish before returning
start profiling: am profile <PROCESS> start <FILE>
stop profiling: am profile <PROCESS> stop
<INTENT> specifications include these flags:
[-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] ...]
[-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]
[--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]
[-e|--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]
[-n <COMPONENT>] [-f <FLAGS>] [<URI>]
Instead of android:deploy and android:run you could just launch your application in debug by eclipse and not by maven. You have to have your project configured properly to do this.
You can deploy and start it using this post. To debug I guess and hope you only need to change some parameters.