how to call method after 2 minutes in background - java

i need to call a method after 2 minutes. i have tried handler and timer but when app close then it doesn't work. then i have call timer in service and start service on button click and stop service after 2 minutes. it works but problem is sometime service calls itself. below is my code.
MyService class
public class MyService extends Service {
private static Retrofit retrofit = null;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
new CountDownTimer(120000, 1000) {
public void onTick(long millisUntilFinished) {
Log.d("message", "start");
}
public void onFinish() {
Log.d("message", "finish");
callMyMethod();
stopService(new Intent(MyService.this, MainActivity.class));
}
}.start();
}
MainActivity class from where i start service.
stopService(new Intent(getContext(), MyService.class));
startService(new Intent(getContext(), MyService.class));
Manifest
<service android:name="MyService" android:enabled="true" android:exported="true"/>
NOTE: I WANT TO CALL SERVICE ONLY ON BUTTON CLICK AND STOP SERVICE AFTER 2 MINUTES.
please need help to solve this issue or If there is other good solution other than services.
Updated: if network response in not success how can i handle to retry.
MyService class
public class MyService extends Service {
private static Retrofit retrofit = null;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
new CountDownTimer(120000, 1000) {
public void onTick(long millisUntilFinished) {
Log.d("mess", "start");
}
public void onFinish() {
Log.d("mess", "finish");
selectDriverForJOb();
stopSelf();//(new Intent(MyService.this, MainActivity.class));
}
}.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
private void selectDriverForJOb() {
SharedPreferences sharedPreferences = getSharedPreferences("Login_credentials", MODE_PRIVATE);
String user_id = sharedPreferences.getString("userID", null);
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
APIServices_interface selectDriver_interface = retrofit.create(APIServices_interface.class);
Call<SelectDriverforJobResult> call = null;
try {
call = selectDriver_interface.selectDriverforJob(user_id);
} catch (Exception e) {
e.printStackTrace();
}
if (call != null) {
try {
call.enqueue(new Callback<SelectDriverforJobResult>() {
#Override
public void onResponse(Call<SelectDriverforJobResult> call, Response<SelectDriverforJobResult> response) {
SelectDriverforJobResult selectDriver = response.body();
String message = selectDriver.getMessage();
if(!(message.equalsIgnoreCase("success"))){
}
}
#Override
public void onFailure(Call<SelectDriverforJobResult> call, Throwable t) {
Log.d("mess : ", "Error Updating ");
//want to retry
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

override onStartCommand in service and return START_NOT_STICKY it will not restart the
public void onStartCommand()
{
return START_NOT_STICKY
}
and use stopSelf() insted of stopService(new Intent(getContext(), MyService.class));

Your Service will not run after app close, Read background restriction.
And this is not really a Service use case.
The solution can be to your problem is AlarmManager . Set an alarm for exact after 2 minutes and your Receiver willget called when its triggered . Before using AlarmManger give a read to setExactAndAllowWhileIdle() and setExact().
Alternatively you can also use WorkManager to set a Exact Job . But This will be an overkill if you do not need Job Constraints. So if your work does not depends of any Constraints like Network connection or other you can go with AlarmManger.
PS:- If your task depends on a Network connection then you should go with WorkManager. Read Schedule tasks with WorkManager .

Related

BLE Advertising on Background

I´m working on a android app of inside of a Contact tracing project. What i need right now is make a background process (idk if, service, foreground service, worker, etc), that can keep the BLE advertiser sending beacons even if the application closes.
Is working without issues on the main thread but when i try to convert in a service, it can´t start.
This is the service class that i tried:
public class AdvertiserService extends Service {
private BluetoothLeAdvertiser advertiser;
private AdvertiseSettings settings;
private AdvertiseCallback callback;
#Override
public void onCreate() {
super.onCreate();
advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
.setConnectable(false)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
.setTimeout(0)
.build();
callback = new AdvertiseCallback() {
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
}
#Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
}
};
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
long userId =
Long.parseLong(PreferenceManager.getDefaultSharedPreferences(this)
.getString(getString(R.string.user_id_pref_key), "0"));
MeetingBeacon beacon = new MeetingBeacon(userId, userId);
Log.d("MEETING_BACON", beacon.getBeaconUUID().toString() );
AdvertiseData data = new AdvertiseData.Builder()
.addServiceData(beacon.getBeaconUUID(), beacon.getBeaconData())
.build();
advertiser.startAdvertising(settings, data, callback);
return START_STICKY;
}
#Override
public void onDestroy(){
Log.d("ADVER-Sv","Automate service destroyed...");
advertiser.stopAdvertising(callback);
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public boolean stopService(Intent name) {
Log.d("SCAN-Sv","Automate service stop...");
advertiser.stopAdvertising(callback);
stopSelf();
return super.stopService(name);
}
}
And i´m starting this service from main thread as:
advertiserService = new Intent(this, AdvertiserService.class);
if(advertiserEnabled) {
ComponentName ret = startService(advertiserService);
if(ret != null){
Log.d("SERVICE:", sv.toString());
}
Log.d("SERVICE ", "fail");
}
But ret is always null , so the service cannot start.
Idk if using service is the better solution in this case.
Anyone can suggest which could be the better solution to solve this problem?

bind to already running Service

Heres my problem:
I am implementing a music player (PlayerActivity.java / xml) which is bound to a service (PlayerService.java) that basically is just an instance of a musicplayer so that it can run in the background. When lefting the app or changing the activity and the restarting the activity i want to bind to the still running service without stopping or restarting it. I have tried using only bindService() but that made me face the problem: somehow without calling startService() before bindService the Service doesn't get initialized or it takes a few milliseconds so that the functions only get null when accessing service functions.
Here is my service class:
public class playerService extends Service {
public boolean running = false;
public MediaPlayer mediaPlayer;
public boolean isPrepared = false;
private String url;
public class serviceBinder extends Binder {
public playerService getService() {
return playerService.this;
}
}
public boolean isRunning(){
return running;
}
private IBinder mBinder = new serviceBinder();
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w("Service", "started");
mediaPlayer = new MediaPlayer();
running = true;
Log.e("!!!", running + "");
return START_STICKY;
}
public void pause() {
mediaPlayer.pause();
}
public void resume() {
mediaPlayer.start();
}
public void setupPlayer() {
try {
if (mediaPlayer != null) {
mediaPlayer.reset();
}
} catch (Exception e) {
Log.e("MediaPlayer", e.getMessage());
}
try {
mediaPlayer.setDataSource(url);
mediaPlayer.prepareAsync();
} catch (Exception e) {
Log.e("MediaPlayerToo", e.getMessage());
}
}
public void reset(){
mediaPlayer.reset();
}
public void updateUrl(String url){
this.url = url;
}
public void start(){
mediaPlayer.start();
}
public int getCurrentPosition(){
return mediaPlayer.getCurrentPosition();
}
public int getDuration(){
return mediaPlayer.getDuration();
}
#Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
mediaPlayer.reset();
}
}
I experimented with waiting until the Service has started with a boolean. But when i add any kind of code
after
mService = binder.getService();
startService(intent);
it seems to not get created at all.
Here is also my onServiceConnected class
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
playerService.serviceBinder binder = (playerService.serviceBinder) service;
Intent intent = new Intent(getApplicationContext(), playerService.class);
mService = binder.getService();
startService(intent);
//... <- adding code here will result in the Service not starting?!!
}
I know that my problem is quite confusing, but this was the best i could come up explaining it. I would be really glad if you had any idea because this problem stops me from deployment. Thank you very much!!

How to make service continues to work after the app is restarted

I have a service works by pressing a button.
There's a counter that works every second inside it.
I tested it and it's working.
It also works after the application is shut down.
The problem after the application is closed
Then I'm doing a run
test the service it doesn't work.
How do I make it works after i do run from inside Android studio ?
//MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!isMyServiceRunning(SensorService.class)){
Log.i("isServiceRunning","Not");
}else {
Log.i("isServiceRunning","Don");
}
}
public void Test(View view){
startService(new Intent(this, SensorService.class));
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
/// Service
public class SensorService extends Service {
public int counter=0;
public SensorService() {
super();
Log.i("HERE", "here I am!");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("EXIT", "ondestroy!");
// Intent broadcastIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);
stoptimertask();
}
private Timer timer;
private TimerTask timerTask;
long oldTime=0;
public void startTimer() {
//set a new Timer
Log.i("startTimer", "Don");
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, to wake up every 1 second
timer.schedule(timerTask, 1000, 1000); //
}
/**
* it sets the timer to print the counter every x seconds
*/
public void initializeTimerTask() {
Log.i("initializeTimerTask", "Don");
timerTask = new TimerTask() {
public void run() {
Log.i("in_timer", "in timer ++++ "+ (counter++));
}
};
}
/**
* not needed
*/
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
#Nullable
#Override
public IBinder onBind(Intent intent){
return null;
}
}
If you use "Run" from Android Studio (regardless if it's tests or the app) the service will always stop first since the whole application will always stop first. The service will not stop if you start the App manually from the device.
There is no way around this and is actually a good feature. It ensures that the App is always started cleanly on every run. If you want to share the reason of why you want to do this, there might be an alternate way of solving your problem.

Immortal Service

I need to implement a project, such as chat. We decided to use the Socket.IO library. FCM is not considered. To receive messages in the background using Service. Here:
public class SocketServiceProvider extends Service {
private Socket mSocket;
private final String EVENT_NEW_MESSAGE = "new_message";
private final String LOG_TAG = "SocketServiceProvider";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.e(LOG_TAG, "created()");
realm = Realm.getDefaultInstance();
startForeground(1, new Notification());
if (mSocket == null)
mSocket = BaseApplication.getSocket();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(LOG_TAG, "onStartedCommand()");
startSocket();
return START_STICKY;
}
private void startSocket() {
if (mSocket.connected()){
stopSocket();
}
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(EVENT_NEW_MESSAGE, onNewMessage);
mSocket.connect();
}
private void stopSocket() {
mSocket.off();
mSocket.disconnect();
}
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
new Handler(Looper.getMainLooper()).post(() -> {
if (mSocket.connected()) {
isOnline = true;
Log.e(LOG_TAG, "Connected!");
}
});
}
};
private Emitter.Listener onNewMessage = args -> {
final JSONObject data = (JSONObject) args[0];
final String username;
final String message;
try {
username = data.getString("from");
message = data.getString("message");
} catch (JSONException e) {
Log.e("MainActivity", e.getMessage());
return;
}
Log.e(LOG_TAG, username + " wrote: " + message);
};
#Override
public void onDestroy() {
super.onDestroy();
Log.e(LOG_TAG, "onDestroy()");
stopSocket();
ContextCompat.startForegroundService(this, new Intent(this, SocketServiceProvider.class));
}
}
The only problem is that when the phone goes into Doze mode, messages do not come. Tried to wake up with AlarmManager in onTaskRemoved(), onDestroy(), unsuccessfully.
Even with onDestroy() tried to call BroadcastReceiver, so that it started back my Service, just did not understand why, but its onReceive() method does not work.
Here is my last option, the code that posted. There is I usе startForegroundService. And this option worked, at least not dying. Only in this case, the battery discharges quickly
Googled, Write that using JobIntentService can be implemented, but nowhere described in detail.
Question: How can this be done and how did you implement such tasks? And how can this be achieved with JobIntentService?

Android service run every 10 seconds makes ANR Message

I have an android application, which contains a main activity which displays information to the user.
When MainActivity starts, A service is created/started which checks a web service on every 10 seconds - if the Web service result will show in a notification.
I start the service from Main activity using Intent,
getActivity().startService(new Intent(getActivity(), NotificationService.class));
I Also try this code, (But same result).
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
getActivity().startService(new Intent(getActivity(), NotificationService.class));
}
});
If service started I get warning In my Logcat,
Skipped 91 frames! The application may be doing too much work on its main thread.
My notification service code,
public class NotificationService extends Service {
// constant
public static final long NOTIFY_INTERVAL = 10 * 1000; // 10 seconds
long current_times;
String c_time;
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
static HttpClient client = new DefaultHttpClient();
private Timer mTimer = null;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#TargetApi(Build.VERSION_CODES.GINGERBREAD) #SuppressLint("NewApi") #Override
public void onCreate() {
// cancel if already existed
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
SharedPreferences.Editor editor = getSharedPreferences("notification_oldtime", MODE_PRIVATE).edit();
editor.putInt("old_trail_time", 0);
editor.putInt("old_sample_time", 0);
editor.putInt("old_neworder_time", 0);
editor.commit();
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
public long current_time_get(){
return current_times;
}
class TimeDisplayTimerTask extends TimerTask {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN) #Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// My webservice code for notification
}
}
}
Try using IntentService instead of Service. IntentService does its work on a separate thread.
serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder binder) {
try {
((NoteBinder) binder).service.startService(new Intent(
MyActivity.this, NotificationService.class));
MyLog.d(TAG, "onServiceConnected is called; "
+ className.getClassName());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
#Override
public void onServiceDisconnected(ComponentName className) {
MyLog.d(TAG, "onServiceDisconnected is called; "
+ className.getClassName());
}
};
bindService(
new Intent(BaseActivity.this, NotificationService.class),
serviceConnection, Context.BIND_AUTO_CREATE);
instead of using start service use bind service.

Categories

Resources