How Thirdparty Apps access All details about installed apps - android

In my app , I am showing the memory usage of each app. I tried the solutions provided in SOF as,
Getting from MemInfo shell command
Process process = Runtime.getRuntime().exec("dumpsys meminfo " + info.packageName);
Permission denied to run this command.
Tried with TOP command
Process process = Runtime.getRuntime().exec("top -n 1 -d 1");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
for(int i=0;i<5;i++)
in.readLine();
do {
try {
String trial[] = in.readLine().split(" ");
int j=0;
String array[]=new String[trial.length];
for(String a:trial)
{
if(!a.isEmpty()) {
array[j] = a;
j++;
}
}
String package_name=array[9];
if(package_name!=null)
{
if(package_name.contains(":"))
package_name=package_name.substring(0,package_name.indexOf(":"));
}
publishProgress(package_name);
Debug.MemoryInfo[] procsMemInfo = manager.getProcessMemoryInfo(new int[] {Integer.parseInt(array[0])});
long memory=0;
for (Debug.MemoryInfo info:procsMemInfo)
{
memory+=info.getTotalPss();
}
processDescriptions.add(new ProcessDescription(array[0], Integer.parseInt(array[1]),
array[2], MemorySizeConverter.MBorKB_Converter((double) memory, 1), array[8], package_name));
}
catch (Exception e)
{
Log.d("skipped",e.toString());
}
} while (in.readLine() != null );
It worked and I can get running processes memory info. Not for all installed apps.
As this statement, My app should be signed with the platform key, or installed in the system partition to access it. But how third party apps available in playstore are accessing it . Can anyone help me.

Related

How to uninstall system apps programatically after Android O?

I am making an app that can uninstall system apps. After going through all the answers from StackOverFlow, I can say that 99% of them are via ADB and the one which I found useful https://stackoverflow.com/a/34399068/9953518 ,this is now changed from Android O.
According to this article https://medium.com/#quaful/the-changes-of-apk-install-location-since-android-oreo-e646d1b53c4d it is now not possible to navigate to a specific folder of the app and we are bound to use .sourceDir. The problem that I have is after requesting for the root and getting the sourceDir, the .apk file doesn't uninstall and if it does, the complete files are not uninstalled or removed in this case. I am using the code below :
//appsSelected is the array with all the package names of the system apps selected to be uninstalled
case "uninstall":
for (int i = 0; i < appsSelected.size(); ++i) {
final int finalI = i;
Thread worker = new Thread(new Runnable() {
#Override
public void run() {
RootManager.getInstance().obtainPermission();
System.out.println("Public directory is "+ yup(appsSelected.get(finalI)));
runCommand("rm -rf "+ yup(appsSelected.get(finalI)) );
}
});
worker.start();
}
break;
This is the fucntion that returns the filePath:
String yup(String pack){
PackageManager m = getPackageManager();
PackageInfo p = null;
try {
p = m.getPackageInfo(pack, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return p.applicationInfo.sourceDir;
}
Finally the function that runs the commands:
public static void runCommand(String command) {
try {
Process chmod = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(chmod.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
chmod.waitFor();
String outputString = output.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
I have the root permission ("su" command) and all the permissions required.
At first, run:
pm uninstall <package_name>
Then,
rm -r <applicationinfo.sourceDir>
Then,
rm -r <applicationinfo.publicSourceDir>
Then reboot the device, and the app should be uninstalled.
N.B: All these command should run as root!

How to execute unix 'top' command with options in android

I am trying to execute 'top' command with following code which is working correctly:
try {
Process proc = Runtime.getRuntime().exec("top");
InputStream is = proc.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is), 500);
StringBuilder output = new StringBuilder();
String line = "";
int count = 0;
while ((line = reader.readLine()) != null) {
if(line.trim().equals(""))
continue;
if (line.trim().startsWith("User")) {
count++;
if (count > 2)
break; //'top' command keeps repeating call to itself. we need to stop after 1 call
}
if (line.contains("PID")) {
mainInfo.append(output.toString());
output.delete(0,output.length());
continue;
}
output.append(line)
.append(CPUInfoUtil.SEPARATOR_LINE); //append this separator to help parsing
}
reader.close();
proc.destroy();
return output.toString();
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
throw new RuntimeException(e);
}
This is returning me all processes including kernel/root processes. I want to get only system processes except woner=root. For that I tried following 'top' with following options, which didn't work:
Process proc = Runtime.getRuntime().exec(new String[]{"top","U","!root"});
I know I can also get running processes using following code but it does not provide additional information that 'top' provides (e.g. Cpu%, thread count etc):
((ActivityManager) act.getSystemService(Context.ACTIVITY_SERVICE)).getRunningServices(Integer.MAX_VALUE);
After doing a lot of homework I got this working! Following way 'top' can be used with as many options:
String[] cmd = {"sh","-c",
"top -m 100 -n 1"
};
Process proc = Runtime.getRuntime().exec(cmd);
I have use -m and -n options and its working great. See manual for whole list of options:
'top' options
I am using
Process psProc = Runtime.getRuntime().exec("top -n 1 -d 5");
to get all the process running and then calculate CPU usage for android apps.

Is it possible to update an android app while it is running and then reload it again

This question might have been asked earlier, but could not get any clear answer. I basically do not want and client interactions with the updates and other stuff, all they can see is the app running and they are happy. But for this to do I need some background thread or something that checks the market for a new update and updates it in the behind and after applying the update reboot the app.
P.S. I am totally new to android development so really sorry if I am sounding crazy, but this is my requirement
You can not update (or install) an app without user-interaction, unless
You're a system app (custom ROM)
Your device is rooted and your updater has root privileges.
Further, there is no official API available to check the version of an app available in the Google Play store.
You can achieve some of what you are trying to do by keeping track of the current version outside of Google Play and then prompting to update the user by launching the market link. If you do that from a secondary app, you can even wait for the update to be complete and then re-launch the app.
In practice, you can't do silent installs/updates without user-interaction, and that's a Good Thing (tm), for the reasons that the first couple of commenters have stated.
AFAIK, it is possible if you have root access, the process is like following:
Your app is in /system/app folder (as a system app)
You need following permissions:
android.permission.INSTALL_PACKAGES
android.permission.DELETE_PACKAGES
android.permission.CLEAR_APP_CACHE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.MOUNT_UNMOUNT_FILESYSTEMS
Your app must be signed with system signature
java -jar signapk.jar platform.x509.pem platform.pk8 helloworld.apk hello.apk
Check for updates in a background thread and download updated .apk file to a temporary place, e.g apk_path
Execute pm install apk_path command programmatically, below is a snippet:
public String silentInstallation(String apkPath)
{
String[] args = { "pm", "install", "-r", apkPath };
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
InputStream errIs = null;
InputStream inIs = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read = -1;
process = processBuilder.start();
errIs = process.getErrorStream();
while ((read = errIs.read()) != -1) {
baos.write(read);
}
baos.write('\n');
inIs = process.getInputStream();
while ((read = inIs.read()) != -1) {
baos.write(read);
}
byte[] data = baos.toByteArray();
result = new String(data);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (errIs != null) {
errIs.close();
}
if (inIs != null) {
inIs.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (process != null) {
process.destroy();
}
}
return result;
}
Hope it helps.

Android Not Granting Dump Permission

For the purposes of monitoring Battery usage etc. I have code that executes a few dumpsys calls, reads and parses the output to extract data that I am interested in.
dumpsys battery, dumpsys statusbar, and dumpsys power all give me an error message for output like "Permission Denial: can't dump Battery service from pid..."
Also, when the application is launched there is an item in the log tagged with "PackageManager" statingNot granting permission android.permissionDUMP to package.... (protectionLevel = 3 ...)"
However, dumpsys cpuinfo and dumpsys netstat work and give me the correct output, which seems to be inconsistent.
I am able to generate dumpsys battery and the like from the adb shell, but when I try to call it programmatically it does not work.
I have tried running this on a HTC Nexus One phone as well as the emulator and get the same results for each. The weird thing is that this code worked on my Nexus One a day ago (before I upgraded from 2.2 to 2.3), and now it does not. Is this because of the upgrade?
An example of the code I am trying to run is as follows:
String command = "dumpsys battery";
try {
String s = null;
Process process = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(process.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(process.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
How do I get the dumpsys to give me the correct output programmatically and how to I get the dump permission to be granted?
*The Nexus One is not rooted and I would like to get this working without having to root it for the purposes of my project
Thank you for your help
Regular applications cannot get the DUMP permission. It is reserved to system applications.
android.permission.Dump is protected by system, signature, and development permission protection levels. Line 1993 of the source shows you this. If your APK is signed with the framework cert, is in the priv-app directory, or debuggable (see below) you can use the pm service to grant the permission, but otherwise the code specifically prevents what you're asking for (line 2624 of source).
Debuggable APKs can be created through setting the debuggable attribute on a buildType via build.gradle. Sample Android DSL:
android {
...
buildTypes {
debug {
debuggable true
...
}
quality_assurance {
debuggable true
}
...
}
If your handset had been rooted, 'dumpsys activity' will work on Android2.3:
private static void dumpIT0(String sCmd) {
try {
String s = null;
String command = "su -c " + sCmd;
Process process = Runtime.getRuntime().exec(command);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(
process.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
Log.e(TAG, "IOException: " + e);
}
}
sCmd = "dumpsys activity";

Can not access android /data folder?

try {
Runtime rt = Runtime.getRuntime();
Process pcs = rt.exec("ls -l /data");
BufferedReader br = new BufferedReader(new InputStreamReader(pcs
.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
Log.e("line","line="+line);
}
br.close();
pcs.waitFor();
int ret = pcs.exitValue();
Log.e("ret","ret="+ret);
} catch (Exception e) {
Log.e("Exception", "Exception", e);
}
only print "ret=0",How to print the correct path?
Android protects it's internal directories. You can only access your directory under /data/data/your_package. I believe that the normal user does not have Read privileges for the /data directory on a normal device.
data folder is inaccessible on a device except by system processes. You cannot access data folder of a unrooted phone through adb. You can access data folder of emulator or rooted phones.
Did you try doing it with your own app, and not by spawning another process (e.g. Runtime.exec())
File dataDir = new File("/data");
String[] files = dataDir.list();
for (int i = 0 ; i < files.length ; i++ ) {
Log.d(TAG, "File: "+files[i]);
}
Also, I'd look at the different read permissions, maybe there's another way to get to the data you're looking for via ContentProviders.
If you'll want to access /data folder not from java code, but from your PC console - you can use a adb shell command. it has no restrictions.
remember to have an emulator running, or connect your phone via USB before running that

Categories

Resources