I'm trying to open the settings app from inside my sample app.
Code snippet inside onCreate:
Process process;
try {
process = Runtime.getRuntime().exec("am start -a android.intent.action.MAIN -n com.android.settings/.Settings");
process.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s = reader.readLine();
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
catch(Exception e) {
e.printStackTrace();
}
When I run this, my app opens, but settings app does not start (neither does any other app I try). The toast inserted for debugging displays "Starting: Intent { act=android.intent.action.MAIN cmp=com.android.settings/.Settings } but it doesn't actually start. Nothing useful visible in logcat either (unless I've missed something in it).
Same command is working using adb (adb shell am start -a android.intent.action.MAIN -n com.android.settings/.Settings)
I'm using Android Studio and an Android 4.4 device if that matters. I've been searching online to figure out what I might be doing wrong, but things seem correct in the above code. Could someone please help?
Update:
Apologies for not giving further details, but Settings is not the app that I finally plan to launch in the actual version of this app, Settings was just a test. It is another app which doesn't have android:exported="true" and takes parameters. To be precise, it opens files of a certain extension which it takes as parameters like "adb shell am start -W -a android.intent.action.VIEW -d ..."
The right way to run another application in Android would be According to this answer
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.android.settings");
startActivity(launchIntent);
Why don't you open Settings by Intent? Something like this:
startActivityForResult(new Intent(android.provider.Settings.ACTION_SETTINGS), 0);
Related
I am working on a device admin app (has been signed by the manufacturer). I am using it to install other apps using the below adb shell command for android 9 :-
cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293
and I am just passing it like this:-
String command = "cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293"
Runtime.getRuntime().exec(command);
But I get the error "cat unknown option S ".
The same command works perfectly fine when I run it from adb shell.
Don't know what I am doing wrong and could use some help.
EDIT 1:-
I tried running the command like below:-
String[] commandInstall = {
"/system/bin/sh",
"-c",
"cat /sdcard/Download/myfolder/newapp.apk | pm install -S 1528293"
};
Process process = Runtime.getRuntime().exec(commandInstall);
But now I get the error:-
ava.lang.SecurityException: Reverse mode only supported from shell
at com.android.server.pm.PackageInstallerSession.doWriteInternal(PackageInstallerSession.java:679)
at com.android.server.pm.PackageInstallerSession.write(PackageInstallerSession.java:612)
at android.content.pm.PackageInstaller$Session.write(PackageInstaller.java:852)
at com.android.server.pm.PackageManagerShellCommand.doWriteSplit(PackageManagerShellCommand.java:2447)
at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:915)
at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:158)
at android.os.ShellCommand.exec(ShellCommand.java:103)
at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21330)
at android.os.Binder.shellCommand(Binder.java:634)
at android.os.Binder.onTransact(Binder.java:532)
at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2821)
at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3856)
at android.os.Binder.execTransact(Binder.java:731)
Edit 2:- Prior to android 9, I could just do the below for installing apps:-
Runtime.getRuntime().exec("pm install -r app.apk");
Looking at the source code of PackageInstallerSession I found that it was changed to :-
switch (Binder.getCallingUid()) {
case android.os.Process.SHELL_UID:
case android.os.Process.ROOT_UID:
break;
default:
throw new SecurityException("Reverse mode only supported from shell");
}
Source
So even if it is a system app, the shell command for install might not work. From the commit messages it seems, this was done to let PackageInstaller do this job.
However it seems this again got changed to at some point, but probably is not included in android 9:-
switch (Binder.getCallingUid()) {
case android.os.Process.SHELL_UID:
case android.os.Process.ROOT_UID:
case android.os.Process.SYSTEM_UID:
break;
default:
throw new SecurityException(
"Reverse mode only supported from shell or system");
}
Source
So if the app is a system app , then the best way would be to use PackageInstaller.
from PackageInstallerSession.java:
switch (Binder.getCallingUid()) {
case android.os.Process.SHELL_UID:
case android.os.Process.ROOT_UID:
case android.os.Process.SYSTEM_UID:
break;
default:
throw new SecurityException(
"Reverse mode only supported from shell or system");
}
If your app is under system/app maybe you have to put it in system/priv-app. Hope the origin of the exception helps you somehow.
I'm not able to debug my app on my android device after I changed the package name (it was working before). I keep seeing the message below in Debug tab when I click the "Run" button.
This is the error message:
Error while executing: am start -n "com.anhnt/com.focuslab.flashlightnotif.activities.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.anhnt/com.focuslab.flashlightnotif.activities.MainActivity }
Error type 3
Error: Activity class {com.anhnt/com.focuslab.flashlightnotif.activities.MainActivity} does not exist.
Error while Launching activity
Make sure that in the Manifest you have updated the information. The manifest file is currently searching to launch MainActivity in com.anhnt/com.focuslab.flashlightnotif.activities and I believe you have refactored the path to reach it.
Change the package name also in the Manifest File and in the Gradle File
My os is MAC OS 10.11.3.
I using Spark as our IM(Instant messaging),but when the IM log out,IM give an error,said:
java.io.IOException: Cannot run program "open": error=2, No such file or directory .
But when Eclipse runs it, it worked well,and when I wrapped it a mac package and installed it and run it, click "log out" button, it throws errors.
In program, when I log out,I launch a new IM,meanwhile,I killed the old IM application.
Furthermore,in terminal,no matter what I run how many times “open -a Spark”,it just open the same IM,
The source as follows:
public boolean restartApplicationWithScript() {
String command = null;
try {
if (Spark.isMac()) {
command = "open -a " + Default.getString(Default.SHORT_NAME);
}
String commands[] = {"open", "/Applications/Spark.app"};
Runtime.getRuntime().exec(commands);
System.exit(0);
return true;
} catch (IOException e) {
Log.error("Error trying to restart application with script", e);
return false;
}
}
The exception seems to be saying that it cannot find the open command. That seems a bit odd, since it is a standard MacOS command. So I suspect that the reason that it cannot be found is that it is not on the PATH.
Try giving the absolute pathname for the open command. Running which open should tell you what it is.
If open is a shell builtin on MacOS, then you will need to create a subshell to run the command.
Thanks for all, i solved it by 2 step :
1, cmdline = { "open", "-na", "Microsoft Excel" }; this add a "n" ,otherwise,it will open the same app 。
2,chmod -R 777 youAppPath,if not do this ,the app can't issue the command
I am trying to update an Apk on Android Remotely. To run the update without the need of user intervention, I am using this post Link .
But the process is returning with the exit code 139 which means Segmentation fault. My tablet is rooted and I have confirmed it.
File file = new File(Constants.UPDATE_APK_PATH);
try {
String[] filenames = file.list();
File apk = new File(file, filenames[0]);
Process pid = Runtime.getRuntime().exec(
new String[] { "su", "-c",
"pm install -r "+apk.getAbsolutePath()});
pid.waitFor();
Can anybody tell what exactly i am doing wrong? The file is present at the location and the signature of both the apk is same.
I'm pretty sure if you use adb install instead of pm install would resolve this issue.
But i believe in this case application does not have enough permissions to install packages.
I'm trying to input text into the current running application (not my own) using the adb input text method, this works if I run it from the command prompt such as 'adb input text "Android" and also if I run it from terminal emulator. However the below code run successfully but produces no output on the screen.. I have also tried various other methods to run shell commands which have also not failed but not output any text..
Anyone know what I am doing wrong?
try {
//Runtime.getRuntime().exec("su");
Runtime.getRuntime().exec("input text \":\"");
} catch (IOException e) {
e.printStackTrace();
}
To inject text into an android app the injector must have
android.permission.INJECT_EVENTS
permission, so it must be a system app.
Your Runtime.getRuntime().exec has not this permission.
If you run your command from Native executable, it works fine.
Build a NDK binary and execute:
char * command = "input text hello%sworld\0";
system( command );//fork and exec input text ...
Maybe you need to use :
Runtime.getRuntime().exec("shell input text");