Im trying to write a simple task killer. I know I shouldnt kill tasks in Android, but Im eager to try something like this. I have the following code:
List<RunningAppProcessInfo> procInfo = activityManager.getRunningAppProcesses();
for (int i = 0; i < procInfo.size(); i++) {
Log.v("proces " + i,procInfo.get(i).processName + " pid:" + procInfo.get(i).pid + " importance: " + procInfo.get(i).importance + " reason: " + procInfo.get(i).importanceReasonCode);
//First I display all processes into the log
}
for (int i = 0; i < procInfo.size(); i++) {
RunningAppProcessInfo process = procInfo.get(i);
int importance = process.importance;
int pid = process.pid;
String name = process.processName;
if (name.equals("manager.main")) {
//I dont want to kill this application
continue;
}
if (importance == RunningAppProcessInfo.IMPORTANCE_SERVICE) {
//From what I have read about importances at android developers, I asume that I can safely kill everithing except for services, am I right?
Log.v("manager","task " + name + " pid: " + pid + " has importance: " + importance + " WILL NOT KILL");
continue;
}
Log.v("manager","task " + name + " pid: " + pid + " has importance: " + importance + " WILL KILL");
android.os.Process.killProcess(procInfo.get(i).pid);
}
procInfo = activityManager.getRunningAppProcesses();
//I get a new list with running tasks
for (int i = 0; i < procInfo.size(); i++) {
Log.v("proces after killings" + i,procInfo.get(i).processName + " pid:" + procInfo.get(i).pid + " importance: " + procInfo.get(i).importance + " reason: " + procInfo.get(i).importanceReasonCode);
}
My problem here is that when I perform this code, I first get the list of all tasks, thats ok. Than I see in the log several lines of:
Sending signal. pid: (processId) SIG: 9
I asume thats a signal to die. But at the end of my code, when I display all running processes, the list is the same as before, no task has been killed. Any ide why? Thank you!
You can't kill other tasks that way because the Kernel will enforce permissions. Try this instead:
ActivityManager activityManager = (ActivityManager) context.getSystemService("activity");
activityManager.restartPackage(packageName);
you will need the following permissions in the manifest:
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
EDIT:
Actually restartPackage is deprecated. use killBackgroundProcesses() instead!
To achieve best result form killProcess , try calling killProcess many times.as
for (int i = 0; i < 10; i++)
{
android.os.Process.killProcess(procInfo.get(i).pid);
}
NOTE:
version 2.2
- killBackgroundProcesses : " This is the same as the kernel killing those processes to reclaim memory; the system will take care of restarting these processes in the future as needed."
ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
am.killBackgroundProcesses("com.est.testetst");
Required Permissions:
android.Manifest.permission.KILL_BACKGROUND_PROCESSES
version 2.1
- restartPackage -" This method is deprecated. (works for version less than 2.2.
This is now just a wrapper for killBackgroundProcesses(String); the previous behavior here is no longer available to applications because it allows them to break other applications by removing their alarms, stopping their services, etc."
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
am.restartPackage(getPackageName());
Required Permissions:
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
Fortunately, killProcess() will only work for you to kill your own processes. You can tell this by reading the documentation.
Related
How I can detect expected apps that can interrupt in DND mode?
Or when the app's notification shows up, can I know that app in the expected list?
Update: After few days investigation, I'm not sure this is good solution but It's the only clue. In NotificationManager#Policy#toString has something like below
return "NotificationManager.Policy["
+ "priorityCategories=" + priorityCategoriesToString(priorityCategories)
+ ",priorityCallSenders=" + prioritySendersToString(priorityCallSenders)
+ ",priorityMessageSenders=" + prioritySendersToString(priorityMessageSenders)
+ ",priorityConvSenders="
+ conversationSendersToString(priorityConversationSenders)
+ ",suppressedVisualEffects="
+ suppressedEffectsToString(suppressedVisualEffects)
+ ",areChannelsBypassingDnd=" + (((state & STATE_CHANNELS_BYPASSING_DND) != 0)
? "true" : "false")
+ "]";
areChannelsBypassingDnd value is the only clue.
Here is the thing a device that we have transmits regular updates of a custom characteristic of a custom service. The service and characteristic in this device is defined via a XML file. This, of course, is referring to the Bluetooth BLE protocol.
What I'm trying to do is create a simple Qt Android App that connects to the device and monitors the update. I've gotten as far as discovering the service and connecting it signal to it. I've done that using this code:
void BLETest::on_stateChanged(QLowEnergyService::ServiceState state){
Q_UNUSED(state);
// Only printing data if all services are in correct state.
for (qint32 i = 0; i < monitoredServices.size(); i++){
if (monitoredServices.at(i)->state() != QLowEnergyService::ServiceDiscovered){
logger->out("There are still services that have not been discoverd",Logger::LC_ORANGE);
return;
}
}
QString msg = "PRINTING SERVICE DATA<br>";
for (qint32 i = 0; i < monitoredServices.size(); i++){
QLowEnergyService *monitoredService = monitoredServices.at(i);
QList<QLowEnergyCharacteristic> clist = monitoredService->characteristics();
msg = msg + "SERVICE: " + monitoredService->serviceName() + ". UUID: " + monitoredService->serviceUuid().toString() + "<br>";
// Checking if this is the service that need connection.
if (monitoredService->serviceUuid() == QBluetoothUuid(QString("0a464eef-af72-43fd-8a8b-1f26f6319dab"))){
QString res;
if (connect(monitoredService,SIGNAL(characteristicChanged(QLowEnergyCharacteristic,QByteArray)),this,SLOT(on_charastericChanged(QLowEnergyCharacteristic,QByteArray)))) res = "true";
else res = "false";
logger->out("CONNECTED TO TARGET SERVICE: " + res,Logger::LC_ORANGE);
}
for (int i = 0; i < clist.size(); i++){
QString name = clist.at(i).name();
if (name.isEmpty()) name = "UNDEFINED NAME";
QByteArray buffer = clist.at(i).value();
//QString value = QString(clist.at(i).value());
QString value = QByteArray(buffer.toHex()) + " (BS = " + QString::number(buffer.size()) + ")";
QString properties = QString::number(clist.at(i).properties());
msg = msg + "CHARACTERISTIC: " + clist.at(i).uuid().toString() + " - " + name + ": " + value + ". PROPERTIES: " + properties + "<br>";
}
if (clist.isEmpty()){
msg = msg + "No characteristics found<br>";
}
}
logger->out(msg);
}
The above functions waits for all services to be discovered then prints the UUID, name and Value for all characteristics of all services. When the service I want to monitored is processed a connection is done to the changedCharacteristic signal.
When I do this the printed value of the characteristic of the service I want to monitor is the original value for that characteristic. However as that value updates I'm not notified (the signal never triggers) and so the value never changes in my app.
Do I need to write some code to actually trigger the signals?
PD: Using the Blue Gecko Demo App I can see the values changing.
EDIT: I decided to use a timer to Poll the value of the characteristic and it never changes. Which might indicate why the signal is never generated either.
You should connect a chracteristic changed handler to the service:
connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(on_characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
In the slot you can explore the data array.
However, the signal (characteristicChanged()) will only emitted by the service if the for this chracteristic notification is enabled. This works only, if the characteritic has a notify property, that should the case in your application.
Currently, I'm working on to get a list of all running applications. I've been able to do this in the following way,
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(mInfo);
List<RunningAppProcessInfo> listOfRunningProcess = activityManager
.getRunningAppProcesses();
Log.d(TAG, "XXSize: " + listOfRunningProcess.size());
l1 = findViewById(R.id.Layout1);
for (RunningAppProcessInfo runningAppProcessInfo : listOfRunningProcess) {
if (runningAppProcessInfo.uid > 1026) {
uID = runningAppProcessInfo.uid;
Log.d(TAG, "ANS " + runningAppProcessInfo.processName + " Id :"
+ runningAppProcessInfo.pid + " UID: " + uID);
}
}
It gives a list of all running applications. Now I want to differentiate these applications on the basis of whether they are Internal or External apps. Is there any way to separate out internal and external apps.
Here is the thread which checks the whether the app is system app or not.
so that if you get the list of apps then you can check the apps whether the apps are system apps or not using the above thread. so that you can separate the apps.
Is there any way that I can, over a period of say a week, see how much CPU each app uses? The only way that I can think of is to repeatedly parse top output but that doesn't seem like the most efficient way to do it. Is there a better way?
To add some context, basically the traceview functionality of the SDK on the phone itself: http://developer.android.com/guide/developing/debugging/debugging-tracing.html
We did it parsing top output, couldn't think of a better way. We needed to monitor all applications, and trace is only good if you need information about your own as you have to add trace code to your application in order to use it.
The app consumes 5% of CPU when running once a sec, aggregating values, writing values to log file, and displaying results on screen.
Unfortunately code is not opened (yet).
One of the problems you'd face monitoring processes over that period of time is that they'll almost certainly be destroyed and created MANY times in that period - this makes it hard to gain useful figures.
If you're not a "reinventing the wheel" type - the free version of the popular SystemPanel App shows how much CPU time each process has used (and over what period) - the full version apparently offers a detailed history of both CPU and memory usage.
You can use the Debug class to monitor the processes
or use this function to calculate CPU usage
Use /proc/stat/ for the total CPU usage (for all CPU's) . For per process usage
private float readCpuUsage(int pid) {
try {
RandomAccessFile reader = new RandomAccessFile("/proc/" + pid + "/stat", "r");
String load = reader.readLine();
String[] toks = load.split(" ");
long idle1 = Long.parseLong(toks[5]);
long cpu1 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4])
+ Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
try {
Thread.sleep(360);
} catch (Exception e) {}
reader.seek(0);
load = reader.readLine();
reader.close();
toks = load.split(" ");
long idle2 = Long.parseLong(toks[5]);
long cpu2 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4])
+ Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
return (float)(cpu2 - cpu1) / ((cpu2 + idle2) - (cpu1 + idle1));
} catch (IOException ex) {
ex.printStackTrace();
}
return 0;
}
source
To get the list of running processes
ActivityManager mgr = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> allTasks = mgr.getRunningTasks(showLimit);
/* Loop through all tasks returned. */
for (ActivityManager.RunningTaskInfo aTask : allTasks)
{
Log.i("MyApp", "Task: " + aTask.baseActivity.getClassName());
}
I saw similar types of posts here.But i am not getting this right.To get the UID of running process i wrote
ActivityManager mgr = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> processes = mgr.getRunningAppProcesses();
String text = "All Process:\n";
for (int i = 1; i <= processes.size(); i++)
{
String s;
s = processes.get(i - 1).processName.toString();
text += "Process:" + i + s + ":UID:" + android.os.Process.getUidForName(s) + "\n";
}
But after completion of loop what i am getting in the string text is all UID value as -1.I put GET_TASKS permission in manifest file.Why i am not getting the UID.Please help.I need this UID to kill the process.
To kill the process i used killBackgroundProcess Method of ActivityManager.It needs package name not the UID
Please see this answer by #seanhodges for reference.
Reading the whole thread might be helpful too.