Android can use adb shell service call SERVICE to communicate with .aidl file, pass arguments and get return value. However, it belongs Android source code. Is it possible I can do the same thing after install non-system app which is written by myself?
For example, I write an app which its package name is com.test.aidl and there is a function inside.
fun add(x: Int, y: Int): Int {
return x +y
}
Can I use adb command, such as adb shell service call com.test.aidl add i32 1 i32 2 and get value 3 on command prompt?
I've resolved this using instrument.
ADB command
adb shell am insrument -e <NAME> <VALUE> <package/runner>
Android
public class Test extends android.test.InstrumentationTestRunner{
#Override
public void onCreate(Bundle bundle) {
super.onCreate(arguments);
value = (String) bundle.get("name");
}
Then use sendStatus api to print on CMD.
Related
I'm setting up a python script for doing some tests on android phones.
I can actually launch a new chrome tab on my phone with ADB:
shell am start -n com.android.chrome/org.chromium.chrome.browser.ChromeTabbedActivity -d "about:newtab" --activity-clear-task
I can't figure out the way I could perform a search on chrome with the search provider included in.
The suggested command by #oss does not care about user settings/defaults , it only require that google chrome is installed!
You may need to create a function like this:
function adbgs () {
local str="${*}";
adb shell am start -n com.android.chrome/org.chromium.chrome.browser.ChromeTabbedActivity -d "google.com/search?q=${str// /+}" --activity-clear-task
}
adbgs how to do stuff;
Or if you want search using default browser :
function adburlopen () {
adb shell am start -a android.intent.action.VIEW -d "${1}"
}
# google
function adbgs () {
local str="${*}";
adburlopen "https://www.google.com/search?q=${str// /+}";
}
# yahoo
function adbys () {
local str="${*}";
adburlopen "https://sg.search.yahoo.com/search?q=${str// /+}";
}
I try to enable/disable wifi programmatically within my Xamarin Ui Test.
I already found this: Android: How to Enable/Disable Wifi or Internet Connection Programmatically. But it seems not to work within the UiTest.
I also tried something like this:
Context appContext = Android.App.Application.Context;
var wifiManager = (WifiManager)appContext.GetSystemService(Context.WifiService);
bool status = false;
wifiManager.SetWifiEnabled(status);
The first line (Android.App.Application.Context) throws an exception:
Message: System.IO.FileNotFoundException : Could not load file or assembly 'Java.Interop, Version=0.1.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065' or one of its dependencies. The system cannot find the file specified.
I'm using following namespaces:
using Android.Net.Wifi;
using Android.Content;
My project has a reference to Mono.Android.
The backdoor approach works fine for me.
The solution that works for me was a combination of:
Android: How to Enable/Disable Wifi or Internet Connection Programmatically
https://learn.microsoft.com/en-us/appcenter/test-cloud/uitest/working-with-backdoors
Some small own changes (for appcontext/context). Just context did not work for me.
1.: Add following line to the AndroidManifest.xml file of the Android project:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
2.: Add following lines to the MainActivity.cs of the Android project:
using Java.Interop;
using Android.Net.Wifi;
[Export("ChangeWifiState")]
public void ChangeWifiState(bool state)
{
Context appContext = Android.App.Application.Context;
var wifiManager = (WifiManager)appContext.GetSystemService(WifiService);
wifiManager.SetWifiEnabled(state);
}
3.: Call following method out of the Xamarin Ui Test:
app.Invoke("ChangeWifiState", false); // true to enable wifi, false to disable wifi
PS: I use Xamarin Forms. I've got four different projects: a core project, an Android project, a Ui project, and a test project.
I just found a second solution without using the actual app.
It uses ADB commands to enable/disable wifi:
var process = new System.Diagnostics.Process();
var startInfo = new System.Diagnostics.ProcessStartInfo
{
WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden,
FileName = "cmd.exe",
Arguments = "/C adb shell am start -a android.intent.action.MAIN -n com.android.settings/.wifi.WifiSettings adb shell input keyevent 19 & adb shell input keyevent 19 & adb shell input keyevent 23 & adb shell input keyevent 82 & adb shell input tap 500 1000"
};
process.StartInfo = startInfo;
process.Start();
This can be used without a rooted device :).
Steps explained:
adb shell am start -a android.intent.action.MAIN -n com.android.settings/.wifi.WifiSettings opens the wifi settings.
adb shell input keyevent 23 enables/disables wifi.
I'm not sure why the command adb shell input keyevent 19 is used, but it works.
adb shell input keyevent 82 clicks the menu button to change back to the original app.
adb shell input tap 500 1000 clicks the coordinate x=500, y=1000 (center of screen).This may need be changed for different solutions.
Sources for this solution:
How to turn off Wifi via ADB?
ADB Shell Input Events
Run Command Prompt Commands
I'm trying to add my package in doze whitelist.
With ($ adb shell dumpsys deviceidle whitelist +PACKAGE), I can add my package in whitelist,
and this command makes change in the file /data/system/deviceidle.xml.
Now, I'm curious about who generate deviceidle.xml.
Is there anyone who knows about deviceidle.xml?
I found a clue in framework module,
IDeviceController.addPowerSaveWhitelistApp(String name) helps to add my package into ;
also, /data/system/deviceidle.xml is updated.
You can check with adb dumpsys
$ adb shell dumpsys deviceidle
$ adb shell cat /data/system/deviceidle.xml
As far as I know, doze whitelisting is done by system creators.
You can ask user for whitelisting via intent action: Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS.
In the DeviceIdleController soruce code you can see that it reads deviceidle.xml
in constructor. It might be that, if you know the file structure and have rooted device you can manually create and edit this file.
#VisibleForTesting DeviceIdleController(Context context, Injector injector) {
super(context);
mInjector = injector;
mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
[...]
}
I open a cmd on windows system, and then input "adb shell am instrument -w com.demo.uia.test/android.support.test.runner.AndroidJUnitRunner" to run android test.
I want to print log in the cmd while run the test, can anyone tell me how to write code to print log? I have tied system.out.println("xx") and Log.i("xx","xx"), but it's useless.
I want to show the log in cmd line, not in logcat.
I solved the problem now, use sendStatus api.
I guess #MoMo did something like this to have logging output in command prompt window:
In your test class define a function:
private void out(String str) {
Bundle b = new Bundle();
b.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "\n" + str);
InstrumentationRegistry.getInstrumentation().sendStatus(0, b);
}
Then simply use it in #Test functions like:
out("Some message...");
The output appears when running the test in Command Prompt window with adb shell am instrument..., but it is not shown in Run window of Android Studio. It somehow filters the output of test runs, and I cannot find a setting to modify this filter.
I have a simplest possible test app, developed with xamarin, deployed to a usb connected droid. With the goal of having one day a working intent url, I'm trying to call my main activity with adb shell am. Here are the first few lines of my MainActivity...
namespace DematAEAT_Android
{
[Activity(Label = "DematAEAT_Android", MainLauncher = true, Icon = "#drawable/icon")]
[IntentFilter(new[] { "AcquireSignedImage" },
Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault })]
public class MainActivity : Activity
{
int count = 1;
Here are two shell commands. In the first, the package manager successfully understands the package name and reports the apk path. In the second, the activity manager fails to resolve the class MainActivity. It fails with or without the namespace.
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb -d shell pm path "fr.company.DematAEAT_Android"
package:/data/app/fr.company.DematAEAT_Android-1/base.apk
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb -d shell am start -n "fr.company.DematAEAT_Android/.DematAEAT_Android.MainActivity"
Starting: Intent { cmp=fr.company.DematAEAT_Android/.DematAEAT_Android.MainActivity }
Error type 3
Error: Activity class {fr.company.DematAEAT_Android/fr.company.DematAEAT_Android.DematAEAT_Android.MainActivity} does not exist.
edit...
And yet, I can launch happily using monkey. The following command works fine. Tis as if there's a problem with the way I'm naming my activity class in the adb shell am call, but I can't spot it.
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb shell monkey -p fr.company.DematAEAT_Android 1
Events injected: 1
## Network stats: elapsed time=170ms (0ms mobile, 0ms wifi, 170ms not connected)
Can anyone tell me how to call this activity?
This was a breaking change in Xamarin Android 5.0
Android Callable Wrapper Naming
The name mangling scheme for Android Callable Wrappers is changing. Previously, the Android Callable Wrapper package name was constructed by lowercasing the namespace name, which would result in packaging failures if more than one assembly contained a type with the same fully-qualified name.
With the 5.0 release, the default package names for Android Callable Wrappers will be based on the MD5SUM of the assembly-qualified name of the type being exported. This allows the same fully-qualified name to be provided from two different assemblies and not get a packaging error.
https://developer.xamarin.com/releases/android/xamarin.android_5/xamarin.android_5.1/#Android_Callable_Wrapper_Naming
You can override that for your Activity by specifying the name in the [Activity] attribute:
[Activity(Name = "fr.company.demeat_android.MainActivity")]
public class MainActivity : Activity {
/* ... */
}
Well who knew? I needed to grub around in my manifest.xml to discover that xamarin is appending a hash as a namespace in front of my activity name. So the adb call that works looks like this...
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb -d shell am start -n fr.company.DematAEAT_Android/md5abda05033ab0415fc7a776c5d9734c74.BrowsableActivity
Starting: Intent { cmp=fr.company.DematAEAT_Android/md5abda05033ab0415fc7a776c5d9734c74.BrowsableActivity }
The story continues here. This will likely be an issue for anyone trying to start a xamarin activity via adb shell am, or trying to start a xamarin activity with an intent, or an intent url.