So if I pop open a command prompt and take a peek at my device's /proc/meminfo, like so:
adb shell cat /proc/meminfo
I get back what you'd expect - a nice long list of data on the device's RAM usage + capacity. But when I try to read that same location from an adobe air android app, using this basic code:
var meminfo:File = new File().resolvePath('/proc/meminfo');
meminfo.addEventListener(Event.COMPLETE, function(e:Event):void {
trace(File(e.target).data);
});
meminfo.load();
... I get nothing, just an empty ByteArray.
So why can I see the contents of /proc/meminfo from the adb shell, but not from the app? Same goes for other stuff in the /proc/ directory - cpuinfo, for instance. I have no problem loading an xml file from the /etc/ directory, though.
It turns out that if you copy memtest (or cputest, etc.) out to another location, somewhere a little friendlier to AIR - say, File.documentsDirectory - then everything goes smoothly.
Your code might look a little like this:
var meminfo_original:File = new File().resolvePath('/proc/meminfo');
var meminfo_copy:File = File.documentsDirectory.resolvePath('meminfo.txt');
meminfo_original.copyTo(meminfo_copy, true);
meminfo_copy.addEventListener(Event.COMPLETE, function(e:Event):void {
trace(File(e.target).data.toString());
});
meminfo_copy.load();
Related
I am trying to get a timestamp of when the currently running Android app was updated during development (e.g. a new APK installed by Android Studio or ADB.). I have tried the following, but both timestamps do not update even though the app has been updated:
val pm: PackageManager = this.getPackageManager()
val appInfo = pm.getApplicationInfo(this.packageName, 0)
val appFile: String = appInfo.sourceDir
val lastWriteTime = File(appFile).lastModified()
val lastUpdateTime = this.getPackageManager()
.getPackageInfo(this.packageName, 0).lastUpdateTime
As you can see in the screenshot below, the lastUpdateTime is 1653240000762 which in my time zone is 2022-05-22 13:20:00 -0400. That is about 12 days in the past as of this writing. The lastWriteTime is 1653239999000 which is 2022-05-22 13:19:59 -0400.
I just re-ran this code from AndroidStudio about one hour ago on 2022-06-03 14:00:00 -0400. Why did the timestamp not change? I know for sure the app was updated because before this change, the code lines shown were not there to show up in the debugger!
There must be a way to do this. Clearly, the code has changed on the Android device. How can I get a measurement of when that happened?
The reason I want this is because I am a developer of an Android library, and I want to make the library clear out some cache information when it detects a new app install during development to make things easier on the app developer.
If I clearly understood your problem, following approach may help you (actually, it may be not the best solution):
Via gradle add constant for timestamp or date:
static def timestamp() {
return System.currentTimeMillis()
}
android {
...
defaultConfig {
...
buildConfigField "Long", "BUILD_TIMESTAMP", timestamp()
}
}
On your main activity at onCreate send BuildConfig.BUILD_TIMESTAMP and current system timestamp wherever you want. For example, write simple web service that accepts such requests and saves it at remote database.
If you want to track only unique installations, you can use instead of build timestamp hash sum for installation apk somehow or use self written code generation lib that would calc hash sum for sources (for example).
Edit: Or you can calc sources hash at build.gradle directly.
My goal is to show a popup window in the Android UI using linux kernel. Is it possible to do so? I checked the SDM driver(DRM driver for QCOM/adreno devices) but I couldn't find an API which does so. I thought of a solution which would be to open app that shows a pop up on screen but I couldn't find an api for starting android apps from the kernel either. I was able to find some information in this thread How to start an app from kernel
However I couldn't find any solid information!
EDIT
I tried launching telegram as a test through am (and I bypassed selinux denial as well) but nothing happened. Here's the code:
static int launch_test(void){
char *envp[] = {
"ANDROID_DATA=/data",
"LOGNAME=shell",
"HOME=/",
"ANDROID_STORAGE=/storage",
"ANDROID_ASSETS=/system/app",
"SHELL=/system/bin/sh",
"EXTERNAL_STORAGE=/sdcard",
"ANDROID_CACHE=/cache",
"USER=shell",
"TMPDIR=/data/local/tmp",
"PATH=/sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin",
NULL};
char *argv[] = {"/system/bin/am", "start", "org.telegram.messenger/org.telegram.ui.LaunchActivity", NULL};
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
I'm looking for a way to open the battery settings screen from an android app.
So far I found the two intents :
Intent.ACTION_POWER_USAGE_SUMMARY
Settings.ACTION_BATTERY_SAVER_SETTINGS
but none of them open this screen.
I was wondering if anyone knows of such a way. It sounds strange that an intent for something so simple doesn't exist
Settings.ACTION_BATTERY_SAVER_SETTINGS on "plain" Android versions will show the settings page you want to show.
Intent.ACTION_POWER_USAGE_SUMMARY will lead to the overview page showing the battery consumption.
Some manufactures such as Samsung build their own implementation over the system one, e.g. in this the "Battery" page. On Samsung devices, you can call this by calling the SmartManager interface directly. An code example:
if (Build.MANUFACTURER == "samsung") {
val intent = Intent()
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
intent.component = ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
intent.component = ComponentName("com.samsung.android.sm", "com.samsung.android.sm.ui.battery.BatteryActivity")
}
try {
activity?.startActivity(intent);
} catch (ex: ActivityNotFoundException) {
// Fallback to global settings
startActivity(Intent(Settings.ACTION_SETTINGS))
}
} else {
startActivity(Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS))
}
It can be the case that you need additional cases for Huawei or Xiaomi as well.
Huawei can be "com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"...
...and the MIU based ones "com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"
I know this is quite old. But a trick I use is going to the appropriate settings screen in the device settings and then while connected to the phone run:
adb shell
dumpsys window windows | grep -E 'mCurrentFocus'
This returns the package name and Activity name currently in focus.
Using that I can check in code if the intent is callable. If it is, I launch it. If it isnt, I might have better luck with a different screen that is near by or explain to the user he needs to do something manually etc... Obviously the more devices you have, the more Intents you can create and check at run time. Im sure there is a list of Intents for different devices online.
I need my app to perform some su commands programatically (phone is rooted).
When done using adb, the commands work.
For instance:
su -c "mkdir /sdcard/testdir" creates a directory called "testdir" in /sdcard.
When I call:
p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
p.waitFor();
It just moves on and no change happens.
I tried reading the input:
DataInputStream dis = new DataInputStream(p.getInputStream());
while((temp = dis.readLine())!=null)
Log.d(ctx.TAG,"shell:"+temp);
But it reports nothing (loop does 0 iterations).
Has anyone ever faced this issue before? How can it be solved?
Needless to day, non-su commands do work programatically with this method.
Note: I gave mkdir as an example (I know it doesn't necessarily require su). I need a lot of varied commands to be performed under su
Thank you!
EDIT: when I call su -c "id" programatically, there's output that uid=0.
I can get stuck on a problem for days, and the moment I gather up the courage to ask about it on StackOverflow, it is solved within minutes.
The fix is:
p=Runtime.getRuntime().exec("su");
DataOutputStream dos = new DataOutputStream(p.getOutputStream());
dos.writeBytes("mkdir /sdcard/testdir\n");
dos.writeBytes("exit\n");
dos.flush();
dos.close();
p.waitFor();
Don't forget \n at the end of each command you write to the DataOutputStream, as it will not work without it.
You wrote that you "need varied commands to be performed under su". Note that the use of "Runtime.exec()" is discouraged by Chainfire, the developer of the most famous SuperSU root app.
It is tempting to use Runtime.getRuntime().exec("su -c [command]");, but you should be aware that [command] should be a single parameter, and thus may require quoting. Unfortunately both quoting the [command] parameter as well as passing the paramaters as separate variables to either Runtime.exec() or ProcessBuilder does not work consistently across all Android versions, and thus this construct should be avoided entirely. It is not impossible to do this right - but there's a high risk of problems.
See the How to SU Document. So you might want to follow his recommendation here:
3.2. Making the call
A common method to call su that avoids the known issues listed above is by creating an interactive shell and piping commands to it. This is done by calling Runtime.getRuntime().exec("su");, and retrieving input and output streams from the returned Process object. Doing this is a fairly straight-forward piece of code, but including the debug logs and checks it's a bit long to reproduce here.
The core code is located here: [libsuperuser :: Shell.java # GitHub]. Shell.run() is a generic call to run shell code, the following more specific (static) utility functions are the ones you will probably end up using:
List<String> Shell.SH.run(String command)
List<String> Shell.SH.run(List<String> commands)
List<String> Shell.SH.run(String[] commands)
List<String> Shell.SU.run(String command)
List<String> Shell.SU.run(List<String> commands)
List<String> Shell.SU.run(String[] commands)
The SH variants are used for a non-root shell, where the SU variants are used for a root shell. These calls return a List containing the output of the shell commands. If there was no output, the list is empty, but not null. The result is only null in case an error occured - including the user not granting your app su access. These are blocking calls.
Note that in debug compiles, all shell STDIN/STDOUT/STDERR will be logged to logcat, and these calls will (intentionally) crash your app if called from the main thread. The reason for this will be discussed in section 4. When to call su.
If you use double quotes, it will work:
su -c ""command with args""
You might be calling Runtime.getRuntime().exec() in main thread and p.waitFor() makes your main thread wait until it executes. Try calling in another thread, like the following snippet.
new Thread(){
#override
public void run(){
p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
p.waitFor();
}.start();
}
This question already has answers here:
Enable USB debugging (under settings/applications/development) programmatically from within an app
(6 answers)
Closed 5 years ago.
Is there any way to turn USB debugging on/off programmatically on Android devices?
Hi this is my first post on here, and normally I wouldn't bother but I see no one wanted to give you the answer despite there being multiple ways to do so.
This is all from my app, I'm "idone" on xda-dev btw. Also some of this code maybe Samsung MSMxxxx specific
If you have root you can indeed. And here are 3 ways to do so despite other people saying otherwise
Method 1(broadcast secret code)
Method 2(set sys.usb.config)
Method 3(set settings global adb_enabled 1)
public String[] SET_DM_PORT_STATUS_LIST = new String[9];{
SET_DM_PORT_STATUS_LIST[0] = "setMTP";
SET_DM_PORT_STATUS_LIST[1] = "setMTPADB";
SET_DM_PORT_STATUS_LIST[2] = "setPTP";
SET_DM_PORT_STATUS_LIST[3] = "setPTPADB";
SET_DM_PORT_STATUS_LIST[4] = "setRNDISDMMODEM";
SET_DM_PORT_STATUS_LIST[5] = "setRMNETDMMODEM";
SET_DM_PORT_STATUS_LIST[6] = "setDMMODEMADB";
SET_DM_PORT_STATUS_LIST[7] = "setMASSSTORAGE";
SET_DM_PORT_STATUS_LIST[8] = "setMASSSTORAGEADB";}
public String[] SET_DM_PORT_CONFIG_LIST = new String[9];{
SET_DM_PORT_CONFIG_LIST[0] = "mtp";
SET_DM_PORT_CONFIG_LIST[1] = "mtp,adb";
SET_DM_PORT_CONFIG_LIST[2] = "ptp";
SET_DM_PORT_CONFIG_LIST[3] = "ptp,adb";
SET_DM_PORT_CONFIG_LIST[4] = "rndis,acm,diag";
SET_DM_PORT_CONFIG_LIST[5] = "rmnet,acm,diag";
SET_DM_PORT_CONFIG_LIST[6] = "diag,acm,adb";
SET_DM_PORT_CONFIG_LIST[7] = "mass_storage";
SET_DM_PORT_CONFIG_LIST[8] = "mass_storage,adb";}
Process su = Runtime.getRuntime().exec("su");
DataOutputStream outputStream = new DataOutputStream(su.getOutputStream());
outputStream.writeBytes("am broadcast -a android.provider.Telephony.SECRET_CODE -d android_secret_code://" + SET_DM_PORT_STATUS_LIST[paramInt]+"\n");
outputStream.writeBytes("setprop sys.usb.config " + SET_DM_PORT_CONFIG_LIST[paramInt]+"\n");
if(SET_DM_PORT_STATUS_LIST[paramInt].contains("adb")){
outputStream.writeBytes("settings put global adb_enabled 1\n");
}
I am in the process of reversing IOTHIDDENMENU.apk and recreating it's methods but without the internal and hidden api it uses.
On a regular device, with a regular app, you can't.
You need a rooted device, with an app in /system/app, then you can.
Anyway, you shouldn't configure such a thing by yourself, the user should be in full control in such a case.
This is not possible in android because for that you have to access Setting.System. For more info take a look here : How can I disable Android USB debugging programmatically
It's not possible without using your own custom firmware that grants access to the security settings. See thread here: http://groups.google.com/group/android-developers/browse_frm/thread/953c6f0eb0fa9bed#
usb debugging is another name for the Android Debug Bridge (ADB). The item you're looking for is here
http://developer.android.com/reference/android/provider/Settings.Secure.html#ADB_ENABLED
great answer :
https://stackoverflow.com/a/17029123/1136074
basicly its:
android.os.Debug.waitForDebugger(); also you can use the following to determine if the debugger is connected:
android.os.Debug.isDebuggerConnected(); //Determine if a debugger is currently att