Android: "Application level" Pause and Resume [closed] - onresume

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I've been trying to get Application Level Pause and Resume similar to an activity's onPause and onResume. I know there's no API that has this functionality.
I try to follow this post: http://curioustechizen.blogspot.com/2012/12/android-application-level-pause-and.html
But I've had no luck so far.
Has anyone been able to achieve this? What paradigm did you use?
Let me know if you need me to paste some code into this question.
Thanks for the help

Another solution to the problem would be to just keep track of the count of onStart() and onStop() calls from every activity. Example:
First, create a class to hold the counts:
public class ActiveActivitiesTracker {
private static int sActiveActivities = 0;
public static void activityStarted()
{
if( sActiveActivities == 0 )
{
// TODO: Here is presumably "application level" resume
}
sActiveActivities++;
}
public static void activityStopped()
{
sActiveActivities--;
if( sActiveActivities == 0 )
{
// TODO: Here is presumably "application level" pause
}
}
}
Then in every activity, simply call the activityStarted() and activityStopped() methods:
#Override
public void onStart() {
super.onStart();
ActiveActivitiesTracker.activityStarted();
}
#Override
public void onStop() {
super.onStop();
ActiveActivitiesTracker.activityStopped();
}

I had the same problem. My aim was to lock the App, if the user abandons it. A simple aim, which i thought would be easy to implement. But all the solutions I found were way to complex. So I came to a simple solution: A time based lock.
Basically it works like this:
Start countdown to lock app in onPause
Stop countdown in onResume
If onResume is not called in time, change to locked
Therefor I created a small little class:
public class ApplicationLock {
private static final String TAG = ApplicationLock.class.getSimpleName();
private static final int LOCK_TIME = 1000; //lock after a second
private static boolean lock = true; //default is locked
private static Handler handler = new Handler();
private static Runnable runnable = new Runnable() {
#Override
public void run() {
lock = true;
Log.i("ActivityTracker", "App locked");
}
};
public static boolean activityStarted()
{
handler.removeCallbacks(runnable);
if(lock)
{
Log.i(TAG, "App resumed - LOCKED");
return true;
}else{
Log.i(TAG, "App resumed - NOT LOCKED");
return false;
}
}
public static void activityStopped()
{
handler.postDelayed(runnable, LOCK_TIME);
Log.i(TAG, "App paused - Starting countdown");
}
Just call activityStopped() in your activities onPause() and activityStarted() in onResume(). Check the result of activityStarted(). If it returns true, lock your app. If the orientation of the app is changed, onResume will be called very quickly after onPause, so the app will not lock.
This solution might not fit every scenario, but in my case it was the best solution. Additionally you can change the countdown, to increase the user experience (The user pressed a wrong button and returns to the app in a few seconds, no need to lock the app). Hope this is useful to someone else.

I have done something very similar to this in an app which used a service that provided GPS functions by several activities. The idea was to only have the service there when one of the activities that used it is visible, and not there when none are visible. In your case, every activity would hook into a service, and you will know when the entire application was paused or resumed by hooking into the service's onCreate() and onDestroy() methods.
Here is a stripped-down example:
Components needed (these could probably be placed into a utility class if you want to reuse them, or I just had them for each activity class):
private boolean mAppActiveServiceBound = false;
private AppActiveService mAppActiveService = null;
private ServiceConnection mAppActiveConnection = new ServiceConnection() {
public void onServiceConnected( ComponentName className, IBinder service ) {
mAppActiveService = ( (AppActiveService.AppActiveBinder) service ).getService();
}
public void onServiceDisconnected( ComponentName className ) {
mAppActiveService = null;
}
};
Then in your onStart() and onStop() methods for each activity:
#Override
public void onStart() {
super.onStart();
mAppActiveServiceBound = bindService( new Intent( this, AppActiveService.class ), mAppActiveConnection, Context.BIND_AUTO_CREATE );
}
#Override
public void onStop() {
super.onStop();
if( mAppActiveServiceBound ) {
unbindService( mAppActiveConnection );
mAppActiveServiceBound = false;
}
}
And finally, the service itself:
public class AppActiveService extends Service {
// Receives interactions from clients:
private final IBinder mBinder = new AppActiveBinder();
/**
* Provides a handle to the bound service.
*/
public class AppActiveBinder extends Binder {
AppActiveService getService() {
return AppActiveService.this;
}
}
#Override
public void onCreate(){
// TODO: Here is presumably "application level" resume
}
#Override
public void onDestroy(){
// TODO: Here is presumably "application level" pause
}
}

Related

how to do something when liferay module stop

i am making cron job like loop to do something using new thread.
when module stop, this thread keeps running, so when i deployed updated module, i'm afraid it will make duplicate thread doing similar task
#Component(immediate = true, service = ExportImportLifecycleListener.class)
public class StaticUtils extends Utils{
private StaticUtils() {}
private static class SingletonHelper{
private static final StaticUtils INSTANCE = new StaticUtils();
}
public static StaticUtils getInstance() {
return SingletonHelper.INSTANCE;
}
}
public class Utils extends BaseExportImportLifecycleListener{
public Utils() {
startTask();
}
protected Boolean CRON_START = true;
private void startTask() {
new Thread(new Runnable() {
public void run() {
while (CRON_START) {
System.out.println("test naon bae lah ");
}
}
}).start();
}
#Deactivate
protected void deactivate() {
CRON_START = false;
System.out.println(
"cron stop lah woooooooooooooooooy");
}
}
i'm using liferay 7
I have populated task that i store from db, so this thread is checking is there a task that it must do, then if it exist execute it.
I'm quite new in osgi and liferay. i've try to use scheduler and failed and also exportimportlifecycle listener but dont really get it yet
think again: Do you really need something to run all the time in the background, or do you just need some asynchronous processing in the background, when triggered? It might be better to start a background task as a one-off, that automatically terminates
Liferay provides an internal MessageBus, that you can utilize to listen to events and implement background processing, without the need for a custom thread
You're in the OSGi world, so you can utilize #Activate, #Modified, #Deactivate (from org.osgi.service.component.annotations) or use a org.osgi.framework.BundleActivator.
But, in general, it's preferable if you don't start your own thread

How do I replace Asynctask with RxJava Observer?

I have a test project with Room database. Using Asynctask I can successfully insert an object with some test data into the database. I'm trying to learn RxJava and replace Asynctask with RxJava's observer, but it doesn't work. I have read alot of documentation and watched tutorials, but I don't think I quite get it. Here's the relevant code:
Here I set my Room object with the data from my List:
for(ObjectForArray item: listToDatabase) {
myRoomEntity.setName( item.getName() );
Log.d( "TAG", myRoomEntity.getName() );
}
Then I try to use RxJava Observable to insert data into the database. This was originally and successfully done using Asynctask:
Observable<MyRoomEntity> myRX = Observable
.just(myRoomEntity)
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() );
myRX.subscribe( new Observer<MyRoomEntity>() {
#Override
public void onSubscribe(Disposable d) {
Log.d("TAG ONSUBSCRIBE", d.toString());
try {
myViewModel.insertDatabase( myRoomEntity );
Log.d( "TAG", "Populating database Success" );
}catch(Error error) {
Log.d( "TAG", error.toString() );
}
}
The OnNext, OnError and OnComplete are empty.
When I run the project it crashes with the error:
Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
I'm obviously using RxJava wrong since the point is to do asynchronous tasks away from the main thread.
i have use RX java in replace of Asyntask as it has been deprecated in android 9
there are multiple replacements that android provides like Executors, threads, Listenable Futures , Coroutines 🔥, so you are looking how to implement this with rxjava and how RX Java java helps your to migrate just add these dependencies first in gradle
implementation "io.reactivex.rxjava2:rxjava:2.2.20"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
once you import lets start working with RX java i will let you know where you can put background task, pre execute, on post execute like asynctask
lets start codding with Rx java first , i have comment in the method that will help you to put the code
Observable.fromCallable(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
/// here is your background task
return true;
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Boolean>() {
#Override
public void onSubscribe(Disposable d) {
//// pre execute here is my progress dialog
showProgressDialog(getString(R.string.scanning));
}
#Override
public void onNext(Boolean aBoolean) {
//// here is on sucess you can do anystuff here like
if (aBoolean){
/// if its value true you can go ahead with this
}
}
#Override
public void onError(Throwable e) {
/// this helps you to go if there is any error show dialog whatever you wants here
Log.e("error of kind",e.getMessage() );
}
#Override
public void onComplete() {
/// when your task done means post execute
}
});
once its done lets start working with implementation
Observable.fromCallable(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
/// here is your background task
uribitmap = getScannedBitmap(original, points);
uri = Utils.getUri(getActivity(), uribitmap);
scanner.onScanFinish(uri);
return true;
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Boolean>() {
#Override
public void onSubscribe(Disposable d) {
//// pre execute here is my progress dialog
showProgressDialog(getString(R.string.scanning));
}
#Override
public void onNext(Boolean aBoolean) {
//// here is on sucess you can do anystuff here like
if (aBoolean){
/// if its value true you can go ahead with this
}
}
#Override
public void onError(Throwable e) {
/// this helps you to go if there is any error show dialog whatever you wants here
Log.e("error of kind",e.getMessage() );
}
#Override
public void onComplete() {
/// when your task done means post execute
uribitmap.recycle();
dismissDialog();
}
});
now i will do this with executors :
/// pre execute you can trigger to progress dialog
showProgressDialog(getString(R.string.scanning));
ExecutorService executors = Executors.newSingleThreadExecutor();
executors.execute(new Runnable() {
#Override
public void run() {
//// do background heavy task here
final Bitmap uribitmap = getScannedBitmap(original, points);
uri = Utils.getUri(getActivity(), uribitmap);
scanner.onScanFinish(uri);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
//// Ui thread work like
uribitmap.recycle();
dismissDialog();
}
});
}
});
You are getting this error because you are trying to insert an Object on the main (UI) thread.
You should do something like this:
Observable.fromCallable(() -> myViewModel.insertDatabase( myRoomEntity ))
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() );
And then use an Observer to subscribe to the Observable.
Please try restructuring your code like this:
Completable.fromAction(() -> myViewModel.insertDatabase(myRoomEntity))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> Log.d("TAG", "Populating database Success"),
throwable -> Log.d("TAG", throwable.toString()))
Considerations:
If your myRoomEntity is not available before this whole construct gets subscribed, make sure you use defer http://reactivex.io/documentation/operators/defer.html
Your subscribe section handlers are operating on "main", that's why you were receiving a crash.
If possible, avoid unnecessary just calls

Observer won't run update in JavaFX GUI

I read much about the JavaFX GUI Model, Plattform->RunLater and Threads, but I still do not figure out how to get this right. I had a JavaFX GUI which on a button click executed a process and updated a Progress Bar and Label. This was running well with Threading and Platform, but I had to Change this to an Observer Model.
I invoke a Progress Tracker in a Singleton Model, which gets updated by the class executing the process and is Observable. I implemented an Observer as well which should update the two UI Elements.
GUI Controller with Button Event
private void createKeyPressed(ActionEvent event) {
// Make Progressbar visible
pbKeyProgress.visibleProperty().set(true);
if (!Check.keyFileExistant() || cbKeyOverwrite.selectedProperty().get()) {
ProgressTracker.getTracker().addObserver(new ProgressObserver(pbKeyProgress, lblKeyProgress));
Creator.createKey(cbKeyLength.getValue());
} else {
}
}
Progress Observer
public class ProgressObserver implements Observer {
private final ProgressBar progressBar;
private final Label statusLabel;
public ProgressObserver(ProgressBar progressBar, Label statusLabel) {
this.progressBar = progressBar;
this.statusLabel = statusLabel;
}
#Override
public void update(Observable o, Object o1) {
Platform.runLater(() -> {
System.out.println("Tracker set to "+ProgressTracker.getProgress() + " " + ProgressTracker.getStatus());
progressBar.setProgress(ProgressTracker.getProgress());
statusLabel.setText(ProgressTracker.getStatus());
});
}
}
Progress Tracker
public synchronized void setTracker(int currentStep, String currentStatus) {
checkInstance();
instance.step = currentStep;
instance.status = currentStatus;
instance.notifyObservers();
System.out.println(instance.countObservers());
}
Creator
public static void createKey(String length) {
Task<Void> task;
task = new Task<Void>() {
#Override
public Void call() throws Exception {
initTracker(0,"Start");
doStuff();
ProgressTracker.getTracker().setTracker(1,"First");
doStuff();
ProgressTracker.getTracker().setTracker(2,"Second");
// and so on
return null;
}
};
new Thread(task)
.start();
}
The Print within the ProgressTracker gets executed. However, if I add a print within the update of the Observer nothing will be printed. If I check within the Progresstracker, the Observer Count is 1.
Why does the Observer not get notified or execute anything, even if the Notify is called? Did I get the Threading and Execution Modell wrong?
The Progress Bar and the Label will also stay on their initial values.
Don't reinvent the wheel. The JavaFX Properties Pattern is a ready-made implementation of the Observable pattern: there is no need to implement it yourself. Additionally, Task already defines methods for updating various properties, which can be called from any thread but will schedule the actual updates on the FX Application Thread. See updateProgress() and updateMessage(), for example.
So you can do, for example:
public static Task<Void> createKey(String length) {
Task<Void> task;
task = new Task<Void>() {
final int totalSteps = ... ;
#Override
public Void call() throws Exception {
updateProgress(0, totalSteps);
updateMessage("Start");
doStuff();
updateProgress(1, totalSteps);
updateMessage("First");
doStuff();
updateProgress(2, totalSteps);
updateMessage("Second");
// and so on
return null;
}
};
new Thread(task)
.start();
return task ;
}
and
private void createKeyPressed(ActionEvent event) {
// Make Progressbar visible
pbKeyProgress.visibleProperty().set(true);
if (!Check.keyFileExistant() || cbKeyOverwrite.selectedProperty().get()) {
Task<Void> task = Creator.createKey(cbKeyLength.getValue());
pbKeyProgress.progressProperty().bind(task.progressProperty());
lblKeyProgress.textProperty().bind(task.messageProperty());
} else {
}
}

Websocket Servlet thread-safe

I'am playing around with WebSocketServlet (tomcat) and I have some question about doing it properly without race condition problems.
I have an instance variable (so non thread-safe) that will keep track of all the websocket connections
HashMap<String,MyServers> myNonThreadSafeVariable = HashMap<String,MyServers>
This is what the HashMap will contain (roughly...)
private final class MyServers extends MessageInbound {
final Set<MyClients> clients = new CopyOnWriteArraySet<MyClients>();
private String serverName;
#Override
protected void onOpen(WsOutbound outbound) {}
#Override
protected void onClose(WsOutbound outbound) {}
#Override
protected void onText(WsOutbound outbound) {}
}
private final class Clients extends MessageInbound {
private int clientID;
#Override
protected void onOpen(WsOutbound outbound) {}
#Override
protected void onClose(WsOutbound outbound) {}
#Override
protected void onText(WsOutbound outbound) {}
}
So now.. during my servlet life time, I am looping through myNonThreadSafeVariable and then maybe also will loop through myNonThreadSafeVariable.clients and then maybe also modified or add a clients or server etc...
For example when a server connect, in his onOpen there will be something like
myNonThreadSafeVariable.put(key,this);
or When a client connects in his onOpen (quit concern about this one)
server = myNonThreadSafeVariable,get(key);
sever.clients.add(this);
Or sometimes when I have to ping all the clients of all the servers:
for (Entry<String, MyServers> entry : myNonThreadSafeVariable.entrySet()) {
MyServers server = entry.getValue();
server.sendMessage("ping||");
for (MyClients member : entry.getValue().clients) {
client.sendMessage("")
}
}
So If I undertand correctly as myNonThreadSafeVariable is global so will myNonThreadSafeVariable.clients etc..
So my question is what is a good practice to avoid race condition in this scenario ?
Using mutex and synchronized on them when access ether the myNonThreadSafeVariable and myNonThreadSafeVariable.clients ? Or should I avoid using an instance variable at all ? But how ?
thanks !
You could use a ReadWriteLock: you block readers and writers when writing, you block only writers when reading:
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock readLock = lock.readLock();
private final Lock writeLock = lock.writeLock();
...
writeLock.lock();
try
{
myNonThreadSafeVariable.put(key,this);
}
finally
{
writeLock.unlock();
}
...
writeLock.lock();
try
{
server = myNonThreadSafeVariable,get(key);
sever.clients.add(this);
}
finally
{
writeLock.unlock();
}
...
readLock.lock();
try
{
for (Entry<String, MyServers> entry : myNonThreadSafeVariable.entrySet())
{
MyServers server = entry.getValue();
server.sendMessage("ping||");
for (MyClients member : entry.getValue().clients)
{
client.sendMessage("")
}
}
}
finally
{
readLock.unlock();
}
Moreover if you want to avoid the read lock you can copy the whole collection and scan the copy, letting the possibility for the original collection to be changed while notifying.

Update UI while working on background

I have an update database operation, that has an activity, which keeps updating the percentage and it runs inside an AsyncTask.
Inside doInBackground() I call the controller that updates the database and keep updating the percentage on the activity, however, if I press home button or back button, the operation is cancelled. What u suggest me to do?
I was trying to start a Service inside doInBackground() so it would run in background, but it looks like its not working.
My code looks like this:
public class UpdateDatabaseAsyncTask extends AsyncTask<Void, Integer, Integer>
{
#Override
public void onPreExecute()
{
mCustomProgressBar.startAnimation();
}
#Override
public Integer doInBackground(Void... params)
{
return mController.updateDatabase();
}
#Override
public void onPostExecute(Integer result)
{
mCustomProgressBar.stopAnimation();
// finish the activity
}
#Override
public void onProgressUpdate(Integer... value)
{
updatePercentageValue(value[0]);
}
public void callPublishProgress(Integer value)
{
publishProgress(value);
}
}
And inside the controller I call the method callPublishProgress(value) passing the current percentage value, so it will publishProgress(value) in the UI.
I was debugging, and I pressed the home/back button, and it just stopped running the worker thread.
Another solution I tried, was starting a Service to run in background no matter the user press home/back button or not, so I thought, and the Service would make a call to the controller method that does the work, and it would call the callPublishProgress(value) to update the percentage value on the UI anyways.
However, what was happening is, the code reach doInBackground() and start the service, but it goes to onPostExecute() immediately, it just didn't wait the service to finish(of course!). So it gives a NullPointerException. I thought of making a loop inside doInBackground() with a flag set in the Service, so it would leave this loop while the service hasn't been finished (I was using an IntentService), but it didn't work anyways.
I thought of using a Timer too. But I don't know.
I was reading the articles in documentation about Threads, etc. And it suggests using AsyncTask, just as I was trying to do. It also talks about runOnUiThread(Runnable).
Anyways what I need is to make an operation in background(probably using an IntentService), so no matter if the user press the home button, it will keep running, but it must update the percentage on the UI, and when the user leave the screen and back to it, it shows the current percentage value updated in the screen.
What is the best solution for my case?
Thanks.
public class MyServce extends Service{
public static final String BROADCAST_ACTION = "com.myapp";
Intent intent;
private final Handler handler = new Handler();
#Override
public void onCreate()
{
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
}
#Override
public void onStart(Intent intent, int startId) {
handler.removeCallbacks(sendUpdatesToUI);
handler.postDelayed(sendUpdatesToUI, 1000); // 1 second
}
private Runnable sendUpdatesToUI = new Runnable() {
public void run() {
DoYourWorking();
handler.postDelayed(this, 1000); // 1 seconds
}
private void DoYourWorking() {
........
........
intent.putExtra("key", progress);
sendBroadcast(intent);
}
};
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(sendUpdatesToUI);
}
Now in your Activity register broadcast to service
private BroadcastReceiver brodcast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//intent.getWhatever
// update your progress
//progressbar.setProgress
}
register broadcast
registerReceiver(brodcast, new IntentFilter(MyService.BROADCAST_ACTION));
This worked for me. I started a background service on a thread that just fetches the values and updates an object in a singleton.
In the view controller, I start a timer that keeps updating the view by fetching data from the object in singleton.
I had a little problem understanding your entire question text, so I'm not sure if you have tried this. But this is what worked. Also, the service was started with START_STICKY
Use an IntentService (which is a Service on a thread of its own), and Handler to pass the data back to the Activity.

Resources