I am working on a open source application (droidwall fork) and i am stuck with one of the issue were the iptables rules were not applied properly when the system reboots. it works perfectly on most of the android versions. But on some specific ROMS (CM 10.1) it gives the following logcat
12-26 08:39:27.116 I/ActivityManager(582):
No longer want dev.ukanth.ufirewall (pid 2297): empty #17
My code works somethings like below,
private Handler mHandler = new Handler(Looper.getMainLooper());
#Override
public void onReceive(final Context context, final Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
if (Api.isEnabled(context.getApplicationContext())) {
final Handler toaster = new Handler() {
public void handleMessage(Message msg) {
if (msg.arg1 != 0) Toast.makeText(context, msg.arg1, Toast.LENGTH_SHORT).show();
}
};
mHandler.post(
// Start a new thread to enable the firewall - this prevents ANR
new Runnable() {
#Override
public void run() {
if (!Api.applySavedIptablesRules(context.getApplicationContext(), false)) {
// Error enabling firewall on boot
final Message msg = new Message();
msg.arg1 = R.string.toast_error_enabling;
toaster.sendMessage(msg);
Api.setEnabled(context.getApplicationContext(), false, false);
}
}
});
// Start a new thread to enable the firewall - this prevents ANR
}
/*Intent i = new Intent(context, StartupService.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(i);*/
}
You can find my Api.java class here.
12-26 08:39:27.116 I/ActivityManager(582): No longer want dev.ukanth.ufirewall (pid 2297): empty #17
This log means that you have reach the maximum allowed empty processes. (16 is the max in your case)
More about empty processes from android doc:
A process that doesn't hold any active application components. The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.
So, not sure the log you have is directly related to your issue with iptables rules.
After the method onReceived() finished, the system assumes that you're done with the BroadcastReceiver and set the hosted process as lowest priority. And we know that the toaster Handler's handleMessage() method is called asynchronously which is called after the onReceived() method finished, and there is no guarantee that the process is still there to perform the callback method
On most Android versions, the number of processes that running at system start-up is not so many and your process (with lowest priority) has a chance to stay alive until the callback method handleMessaged() is called, but with ROMS (CM 10.1), there might be so many processes running that that moment, system has to kill lower priority processes to free up resources so that higher priority processes can run properly and your process is one good candidate to be killed.
I suggest you start a service to do those asynchronous tasks, that makes your process has higher priority (service-process priority by default or you can use startForeground() method to get the foreground-process priority)
Maybe you can use mHandler.post with some delay to test your case like 20 seconds?
Related
Hi Android geeks over there,
I am developing an application which uses 'com.firebase:firebase-jobdispatcher:0.8.5' to schedule jobs. But the jobs are not getting executed in the tested device.
While I checked the dumpsys activity service GcmService I got the following log, in which my job is marked as Not yet run.
What would be the possible reason for this behavior?
I also found a status like READY_BATTERY_LOW, is it because my devices is running low on battery? But while the testing is taking place, the device is having 58% battery.
Also, the device is connected to Jio 4g network.
The dumpsys log is included below, could anyone have some comments to give a light on the issue. :)
(scheduled) com.mypackage.testapp/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="test-sync-job" trigger=window{start=300s,end=360s,earliest=-459s,latest=-399s} requirements=[NET_ANY] attributes=[RECURRING] scheduled=-759s last_run=N/A jid=N/A status=READY_BATTERY_LOW retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1}
Not yet run.
Thanks in advance :)
Here is the bit of making a vocation.
Driver = new GooglePlayDriver(context);
firebaseJobDispatcher = new FirebaseJobDispatcher(driver);
Occupation constraintReminderJob = firebaseJobDispatcher.newJobBuilder()
.setService(ReminderService.class)
.setTag(REMINDER_JOB_TAG)
.setConstraints(Constraint.DEVICE_CHARGING)
.setLifetime(Lifetime.FOREVER)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(
REMINDER_INTERVAL_SECONDS,
REMINDER_INTERVAL_SECONDS + SYNC_FLEXTIME_SECONDS
))
.setReplaceCurrent(true)
.assemble();
firebaseJobDispatcher.schedule(constraintReminderJob);
How about we investigate the above scrap.
Occupation
There are a few ascribes to make an occupation.
A string label that (inside your application) particularly recognizes the Job.
A JobService subclass that will contain all the business rationale identified with the Job.
A JobTrigger will establish that the made Job is presently prepared to execute.
An arrangement of Constraints is required keeping in mind the end goal to execute the made activity. As a matter of course, it is unfilled which implies that Job will be kept running when the JobTrigger is initiated.
A RetryStrategy is in charge of taking care of the disappointment conditions. The default is taken care of utilizing exponential backoff procedure.
A lifetime that indicates the season of the activity in which it ought to stay planned. The
default is to keep the Job planned until the following boot.
Package is for client provided additional items. This is a discretionary parameter.
A boolean demonstrates whether the Job should rehash or not. The default is false which implies that the planned Job will execute just once.
A boolean shows whether the booked Job ought to supplant any prior Job
with a similar tag or not. The default an incentive for this boolean banner is false.
Once your activity is prepared, you can utilize plan() strategy to plan the activity.
open static void scheduleJob(Context setting) {
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
Occupation work = createJob(dispatcher);
dispatcher.schedule(job);
}
ReminderService.class
open class ReminderService broadens JobService {
/**
* This asynctask will run a vocation once conditions are met with the imperatives
* As soon as client gadget gets associated with the power supply. it will produce
* a warning demonstrating that condition is met.
*/
private AsyncTask mBackgroundTask;
#Override
open boolean onStartJob(final jobParameters) {
mBackgroundTask = new AsyncTask() {
#Override
ensured Object doInBackground(Object[] objects) {
Setting = ReminderService.this;
ReminderTasks.executeTasks(context, ReminderTasks.ACTION_CHARGING_REMINDER);
Log.i("TAG", "onStartJob");
return invalid;
}
#Override
secured void onPostExecute(Object o) {
/* false means, that activity is finished. we would prefer not to reschedule it*/
jobFinished(jobParameters, false);
Log.i("TAG", "onStartJob-OnPost");
}
};
mBackgroundTask.execute();
return genuine;
}
#Override
open boolean onStopJob(JobParameters jobParameters) {
on the off chance that (mBackgroundTask != invalid) {
mBackgroundTask.cancel(true);
}
Log.i("TAG", "onStopJob");
/* genuine means, we're not done, if you don't mind reschedule */
return genuine;
}
}
There are three strategies that will be utilized while utilizing FireBase Job Dispatcher.
onStartJob(JobParameters params)- This is the underlying strategy that will be conjured when a vocation is called. It keeps running on the fundamental string. It will restore a Boolean which tells whether an occupation is remaining or not. Returning genuine demonstrates that more work is remaining. We can call jobFinished() when the activity is finished.
onStopJob(JobParameters params)- This technique is considered when your activity is halted. The activity can be halted because of different reasons if the running limitations related to the activity are never again fulfilled. It will restore a Boolean which tells whether work ought to be attempted again or not. On the off chance that returned genuinely, at that point, the system will set up this activity again for execution.
jobFinished(JobParameters params, boolean needsReschedule)- When work has been offloaded to another string, it ought to be called expressly.
Currently, in my main app, I am sending multiple texts to status bar object.
My status bar object, is going to display multiple texts sequentially, with sleep time of N seconds for each display interval.
Here's my implementation in my main app.
public synchronized void setNextText(final CharSequence text) {
if (executor == null) {
executor = Executors.newSingleThreadExecutor();
}
executor.execute(new Runnable() {
#Override
public void run() {
Fragment fragment = getTargetFragment();
if (fragment instanceof OnStatusBarUpdaterListener) {
((OnStatusBarUpdaterListener)fragment).setNextText(text);
try {
// Allow 1 seconds for every text.
Thread.sleep(Constants.STATUS_BAR_UPDATER_TIME);
} catch (InterruptedException ex) {
Log.e(TAG, "", ex);
}
}
}
});
}
Now, I would like to have the same behavior in app widget. I was wondering, is using Executor being recommended in app widget environment? If not, what class I should use to achieve the similar objective?
I do have experience in using HandlerThread + AlarmManager in app widget. It works good so far. However, the operation done by the runnable is one time. It doesn't sleep and wait.
The following is the code which I use to update stock price in fixed interval.
// This code is trigger by AlarmManager periodically.
if (holder.updateStockPriceHandlerThread == null) {
holder.updateStockPriceHandlerThread = new HandlerThread("updateStockPriceHandlerThread" + appWidgetId);
holder.updateStockPriceHandlerThread.start();
holder.updateStockPriceWorkerQueue = new Handler(holder.updateStockPriceHandlerThread.getLooper());
holder.updateStockPriceWorkerQueue.post(getUpdateStockPriceRunnable(...
}
However, I have a feeling that, for use case "display multiple texts sequentially, with sleep time of N seconds for each display interval", AlarmManager might not be a good solution. Imagine I have 100 texts. Having to set 100 alarms for 100 texts doesn't sound good...
An AppWidgetProvider is a subclass of BroadcastReceiver. Once your callback (e.g., onUpdate()) returns, your process can be terminated at any point.
If that is not a problem — if you fail to finish the semi-animation that you are doing, that's OK — using an Executor from onUpdate() could work.
If you want to make sure that the text changes go to completion, delegate the app widget updating to a Service, where you use your Executor. Call stopSelf() on the Service when you are done, so it can go away and not artificially keep your process around.
Well the singleThread instance work creates an Executor that uses a single worker thread. meaning only thread to process your operation. But in you case use at least two. Your operations sounds expensive.
To conclude your question stick with the executor service as it thread safe.
I have a service on the app which needs to run indefinitely - even when app is closed. It's going to ping a network source, if a state changes then the service must trigger a notification. The loop triggering the pings in the service is user chosen, with the smallest value of 5000ms (5 Seconds). I have the pings on a separate thread (off the UI thread) with calls to a handler thread to post toasts (temporarily while programming) to the UI thread.
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast successMessage = Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT);
successMessage.show();
//sendToastOnUIThread(1000);
new Thread(new Runnable(){
public void run() {
while(true) {
try {
Thread.sleep(GLOBAL_PING_TIMER);
} catch (InterruptedException e) {
e.printStackTrace();
}
sendToastOnUIThread();
//Code for pings here...
}
}
}).start();
return START_STICKY;
}
Above you can see my onStartCommand from the service - when testing this, I only used the code above and left out my code to ping the network source etc.
Incase you wonder whats in 'sendToastOnUIThread();'
public void sendToastOnUIThread(){
Handler h = new Handler(AutoPingServerService.this.getMainLooper());
h.post(new Runnable() {
#Override
public void run() {
Toast.makeText(AutoPingServerService.this,"Servers Pinged",Toast.LENGTH_SHORT).show();
}
});
}
So when this service is running, I get the toasts every 5 seconds, but the service memory just keeps stacking up (seems to cap at 8.5mb) but starts off around 1mb and just builds up around 0.1mb per loop. Am I making too many threads somehow? There should only be the UI thread, the new thread to handle the pings and the handler thread to post toasts when I need them (this will be replaces with notifications once it works)
Open to ideas - fairly new to android development, I wouldn't be surprised if i'm using all the wrong thread types. Possibly this is normal?
EDIT: Spelling.
Okay update for anyone curious:
The memory does get wiped after a while (pweh) as you'll reach a terminal capacity. Not sure if this is ideal but hey - I'm not going to sell it for millions, if the app crashes, I'll update this post. Don't fix what's not broken eh?
Anyway - #Deev kindly said I should move to an IntentService, I did not. I possibly will in the future, but this method works (Although it does look simpler to use a IntentService).
in the beginning I thought it would be fairly simple, but I guess it's not.
I want to call a URL every 10 minutes, either when the app is in the background or
in the foreground. How can I realize this?
I'd use a Service with a Handler inside. Using directly Threads is another approach but it's more likely it will be killed if the Android OS needs to free memory.
The Handler part would be something like this:
boolean stopHandler = false;
Runnable runnable = new Runnable() {
#Override
public void run() {
// Do whatever you need
...
if (!stopHandler) {
handler.postDelayed(this, 600000); // 10 minutes
}
}
};
In iOS 7 you can schedule background operations for periodically fetching data from the network. This tutorial is an example of scheduling background fetch operations -
My problem is make a function to set up themes in my application every 00:00 AM if there are new themes. As I know, to do this problem we must use a loop.
Here is my code:
private void updateThemes() {
Thread time = new Thread() {
public void run() {
int time = 0;
while(time > 86400000) {
//invoke method or start new activity
}
}
};
}
Please help me - Thanks.
Running a thread and waiting for a full day is not going to work. What if the phone is shutdown? What if the user switches to another app and your app is closed by Android because it needed the resources? Besides, it's not very battery friendly either.
You'd better use the Android AlarmManager to set the times at which you would like to check for updates. Also specify a BroadcastReceiver in your app that will receive and process the alarms. There's an example application that does this here or check this post for more info.