I am using a background service to play an audio whenever the user selects a button. But what I would like to do is play the audio every 60 minutes. How would I go about doing this?
I have already tried using a handler and setting the timer to 60 minute then executing the line of code that plays the audio but it just plays the audio automatically whenever the use selects the button.
public class BackgroundService extends Service {
private MediaPlayer player;
private Boolean state = false;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//i would like to play this audio every 60minute in the background
player = MediaPlayer.create(BackgroundService.this, Settings.System.DEFAULT_RINGTONE_URI);
//this will make the ringtone continuously playing
player.setLooping(true);
//staring the player
player.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
//stopping the player when service is destroyed
player.stop();
}
}
It's possible with BroadcastReceiver
Set AlarmManager with your time interval
Intent intent = new Intent("Your Broadcast Receiver");
PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, time_interval, pendingIntent);
Specify your BroadcastReceiver in Manifest.xml
<receiver android:name="com.package.YourReceiver">
<intent-filter>
<action android:name="Your Broadcast Receiver" />
</intent-filter>
</receiver>
try to loop your handler
final Handler handler = new Handler();
int count = 0;
final Runnable runnable = new Runnable() {
public void run() {
// do the task here
Log.d(TAG, "runn test");
if (count++ < 5)
//will continue to loop 5 times
handler.postDelayed(this, 5000);
}
};
// trigger first time
handler.post(runnable);
Related
I'm developing a countdown app, and currently trying to show a notification when you exit the app while the countdown is running. Correspondingly, I want the notification to disappear when the user returns to the app.
So far I've managed to make it work for a simple notification with static text, do the following: in MainActivity.java, in onStop(), I create an intent and initiate the service with startService(intent). Symmetrically, in onStart() I run stopService(intent) so that when you return to the app the service gets canceled. This works like a charm, the notification appears and disappears when it must.
The next step has been trying to make the notification show a text that varies (it will say "X minutes remaining"). According to the info out there, to update an existing notification you have to create a new one, give it the same ID as the existing one, and call .notify of a NotificationManager. When I do this the notification indeed gets updated correctly (the text changes as expected), BUT: now, returning to the main activity does not cancel the notification. The icon stays up there and doesn't get interrupted.
I've been trying to solve this for hours and hours. I've also tried hacks like sending signals via shared preferences to tell the service to stop, but for some reason, it seems to completely ignore the command stopself() too.
Does anybody have a suggestion of what could be the cause? Any help would be greatly appreciated. Here is the relevant code:
MainActivity.java:
#Override
protected void onStart() {
super.onStart();
Intent serviceIntent = new Intent(getBaseContext(), CounterService.class);
stopService(serviceIntent);
}
protected void onStop() {
super.onStop();
Intent serviceIntent = new Intent(getBaseContext(), CounterService.class);
startService(serviceIntent);
}
CounterService.java:
public class CounterService extends Service {
Notification notification;
NotificationManager notificator;
Intent intentNoti;
CountDownTimer counter;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
intentNoti = new Intent(this, MainActivity.class);
final PendingIntent pending = PendingIntent.getActivity(this, 0, intentNoti, 0);
final Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.common_full_open_on_phone);
//Countdown
counter = new CountDownTimer (30000, 1000) {
public void onTick(long millisUntilFinished) {
String time = String.valueOf(System.currentTimeMillis());
notification = new Notification.Builder(CounterService.this)
.setContentTitle("Name")
.setContentText(time)
.setSmallIcon(R.drawable.icon_start)
.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pending)
.setOngoing(true).build();
notificator = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificator.notify(1001, notification);
}
public void onFinish() {
}
}.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
counter.cancel();
}
}
First create a Timer like this
private Timer timer;
private TimerTask timerTask;
public void startTimer() {
timer = new Timer();
timerTask = new TimerTask() {
public void run() {
// Add your code
}
};
timer.schedule(timerTask, 1000, 1000); //
}
Also you need to stop your timer.
So
public void stoptimertask() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
Call StartTimer and StopTimer in OnStartCommand() and onDestroy() respectively. Add these lines in onDestroy()
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, Restarter.class);
this.sendBroadcast(broadcastIntent);
it can be handled in multiple ways, you have not stopped your timer
Note:- posting code in Kotlin
1)
override fun onDestroy() {
counter.cancel()
}
in your activity
override fun onResume() {
super.onResume()
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.cancelAll()
}
This question already has answers here:
Android Handler Periodically
(3 answers)
Closed 6 years ago.
I had a very simple question, I'm trying to update my app with data from my database every 1 minute. I have a method called "SendRequest" which collects the data from my database.
How would I execute this method every 1 minute? I'm not sure where to start with it.
Thanks!
It work In android
Put Your sendRequest method in a thread
protected void onCreate(Bundle savedInstanceState)
{
Handler customHandler = new Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
//enter "sendRequest" method here
}
customHandler.postDelayed(this, 60000);//you can put 60000(1 minut)
}
};
the above code will send request in every minut
First add this to your manifest
<receiver android:name=".NetWatcher" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<service
android:name=".location_service"
android:enabled="true" >
</service>
After that add this two classes in your project
public class location_service extends Service {
LocationManager locationManager;
AlarmManager alarmMgr;
PendingIntent pendingIntent;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public void onCreate(){
alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, NetWatcher.class),PendingIntent.FLAG_CANCEL_CURRENT);
// Use inexact repeating which is easier on battery (system can phase events and not wake at exact times)
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),1000*60*1,pendingIntent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
super.onStartCommand(intent, flags, startId);
// Write your method here
return START_STICKY;
}
}
And
public class NetWatcher extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//start service
Intent in = new Intent(context, location_service.class);
context.startService(in);
}
}
After that write your method inside onStartCommand. start servise from your main activity first time
Intent in = new Intent(context, location_service.class);
context.startService(in);
it will run background mode also.
You can acheive it like this:
class MyClass{
public static void main(String[] args){
while(true){
Thread.sleep(60000);
SendRequest();
}
}
}
This is my code
MyService.java
public class MyService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
class BackgroundTask extends AsyncTask<String,Void,String>
{
//My database upload code
}
}
private void ping() {
try {
BackgroundTask backgroundTask = new BackgroundTask();
backgroundTask.execute(); //Running asynctask
} catch (Exception e) {
}
scheduleNext();
}
private void scheduleNext() {
mHandler.postDelayed(new Runnable() {
public void run() {
ping();
}
}, 300000);
}
public int onStartCommand(Intent intent, int x, int y) {
mHandler = new android.os.Handler();
ping();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
autostart.java
public class autostart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
intent=new Intent(context,MyService.class);
context.startService(intent);
}
}
In AndroidManifest.xml i have these:
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<receiver android:name=".autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".MyService"
android:enabled="true"
>
</service>
I sometimes see this in logcat
02-04 19:57:25.125 10329-10377/com.example.pc.googlemaps I/GMPM: App measurement is starting up
02-04 19:57:25.135 10329-10377/com.example.pc.googlemaps E/GMPM: getGoogleAppId failed with status: 10
02-04 19:57:25.135 10329-10377/com.example.pc.googlemaps E/GMPM: Uploading is not possible. App measurement disabled
This service sometimes doesn't run sometimes run correctly. I check Application Manager from my phone and i see that it runs but as i said sometimes my codes work sometimes doesn't work. For example when i switch on my phone new, i check App Manager and service of my program runs. I couldn't solve where is problem.
I mean, it seems MyService always runs in App Manager but codes sometimes run sometimes doesn't run.
And i noticed that, when i check App Manager from my phone, if MyService is 4-5 MB, it doesnt run, if 13-15 MB it runs. I dont know it is coincidence or not.
Thanks for your help
please check this out
this is my service that getting coordinate every 15 sec and save it to SQLITE, send all the saved coordinates to server every 5 minutes and send an complete coordinates + address to server every 10 minutes
don't mind the content of onDestroy method
it's just my private library
FYI: dont use handler in onCreate method, it'll cause your apps become not responding
believe me, I've try it before
instead use AlarmManager for a better performance
public class service extends Service{
private AlarmManager alarm;
private PendingIntent addData, sendData, fullData;
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
if(!App.User.GetUserCode().equals("")){
App.DataFrame.InfoLog("Location is turned OFF");
App.DataFrame.Off();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
stopAlarm();
Intent stoploc = new Intent(service.this, LocationProvider.class);
service.this.stopService(stoploc);
stopForeground(true);
stopSelf();
App.User.Logout();
App.Toast("Stopping Service");
}
}, 1000);
}else{
stopAlarm();
Intent stoploc = new Intent(service.this, LocationProvider.class);
service.this.stopService(stoploc);
stopForeground(true);
stopSelf();
App.Toast("Stopping Service");
}
super.onDestroy();
}
public void stopAlarm(){
alarm.cancel(addData);
alarm.cancel(sendData);
alarm.cancel(fullData);
}
#Override
public void onCreate() {
App.Toast("Starting Services");
alarm = (AlarmManager) getSystemService(App.GetContext().ALARM_SERVICE);
Intent intent = new Intent(this, CoorReceiver.class);
addData = PendingIntent.getBroadcast(this, 0, intent.putExtra("Code", 0), PendingIntent.FLAG_UPDATE_CURRENT);
sendData = PendingIntent.getBroadcast(this, 1, intent.putExtra("Code", 1), PendingIntent.FLAG_UPDATE_CURRENT);
fullData = PendingIntent.getBroadcast(this, 2, intent.putExtra("Code", 2), PendingIntent.FLAG_UPDATE_CURRENT);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, 15000, 15000, addData);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, 30000, 30000, sendData);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, 600000, 600000, fullData);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent intent2 = new Intent(this, MainActivity.class);
intent2.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intent2, 0);
Notification noti = new Notification.Builder(getApplicationContext())
.setContentTitle("Imagine")
.setContentText("Service is Running")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendIntent)
.build();
startForeground(1234, noti);
return START_STICKY;
}
}
I have a BroadcastReceiver that starts my service, this service it uses async to make an HTTP request and then display a notification, but I'm not getting the service to be run every time the system starts automatically, and then every 1 minute.
Here is my AndroidManifest:
<receiver android:name=".notificar.InicializarServico" android:exported="false">
<intent-filter>
<action android:name="INICIALIZAR_SERVICO"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
<service android:enabled="true" android:name=".notificar.ServicoNotificar">
<intent-filter>
<action android:name="SERVICO_ATUALIZAR"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
The code of BroadcastReceiver is here:
public class InicializarServico extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v("NAMURA LANCHES", "O SISTEMA FOI INICIADO");
Log.v("NAMURA LANCHES", "Iniciando o serviço de atualização");
// Preparar Intent para inicializar o serviço
agendar(context, 5);
Log.v("NAMURA LANCHES", "O Serviço sera iniciado em 15 segundos");
}
private void agendar(Context context, int i) {
Intent myIntent = new Intent(context, ServicoNotificar.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, i); // first time
long frequency= i * 1000; // in ms
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), frequency, pendingIntent);
}
}
And here is my service class:
public class ServicoNotificar extends Service{
private String RequestURL = "http://sandbox.omeuprofissional.com/requests/meus_pedidos.php";
private final int duration = 3000;
private static final String ACTION_RESCHEDULE =
"br.com.namuralanches.android.intent.action.SERVICE_RESCHEDULE";
Handler myHandler;
#Override
public IBinder onBind(Intent intent) {
return null;
}
Thread testThread;
boolean threadRunning = false;
#Override
public void onCreate() {
super.onCreate();
myHandler = new Handler();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("NAMURA LANCHES", "Service started");
myHandler.postDelayed(new Runnable() {
#Override
public void run() {
SharedPreferences preferencias = getSharedPreferences("mesa", MODE_PRIVATE);
String registro = preferencias.getString("REGISTRO_MESA", null);
String hashMesa = preferencias.getString("HASH_MESA", null);
if ((registro != null) || (hashMesa != null)) {
new ListarCompras().execute(RequestURL, hashMesa, registro);
}
}
}, 10000);
stopSelf(startId);
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
Log.v("NAMURA LANCHES", "SERVICO DESTRUIDO");
super.onDestroy();
threadRunning = false;
}
}
I made some changes now I'm lost, I'm not even see the log that the service was created, only the log BroadcastReceiver
You will have to use AlarmManager to start your service. To use AlarmManager, you need a pending Intent which you want the alarm to fire.
like so:
First, create a Receiver that will will be fired by an Intent,
in your activity, create the intent that fires the Receiver,
create a pending intent for the intent that fires the receiver, finally 4. use alarm manager to fire the pending intent.
Remember, your Receiver will fire your service via Intent when it receives content from your alarm manager. You can use the setRepeating method of alarmManager to set the repeat time.
Look at this stack overflow post for example How to start Service using Alarm Manager in Android?.
For details, checkout this link(Using with AlarmManager for Periodic Tasks)
https://guides.codepath.com/android/Starting-Background-Services
Hope this help.
I just started on android development and I'm trying to write and a service that runs in the background and will launch an app at a specific time.
The program I wrote is based on a tutorial I came across, basically the app has 2 buttons, a start and stop. Once the user presses the start button, it'll start the background service and will check the time and if the time is right, it'll launch the app.
However I noticed that it doesn't always checks the time, it only does it when the user presses the button. How do I make it so that, it'll keep checking the time, once the user presses the button?.
Here is my code.
MyService.java
public class MyService extends Service{
private static final String TAG = "MyService";
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
//Toast.makeText(this, "Congrats! MyService Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
}
#Override
public void onStart(Intent intent, int startId) {
//Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
startApp("com.example.myApp");
Log.d(TAG, "onStart");
}
#Override
public void onDestroy() {
Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
}
public void startApp(String packageName){
Calendar c = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
String strDate = sdf.format(c.getTime());
if(strDate == "09:00" || strDate == "15:00" || strDate == "21:00"){
Toast.makeText(this,strDate,Toast.LENGTH_LONG).show();
Toast.makeText(this,"Starting the App",Toast.LENGTH_LONG).show();
Intent intent = getPackageManager().getLaunchIntentForPackage(packageName);
if(intent != null){
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
}
}
MainActivity.Java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//start the service
public void onClickStartServie(View V)
{
//start the service from here
startService(new Intent(this, MyService.class));
}
//Stop the started service
public void onClickStopService(View V)
{
//Stop the running service from here
//Service will only stop if it is already running.
stopService(new Intent(this, MyService.class));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
I think using alarm manager will be a better option. Set an alarm for that time and receive broadcast in your receiver at that time like below code:
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, AppConstants.ALARM_ID_TESTING, new Intent(
AppConstants.FILTER_TESTING), PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + millisAfterCurrent, pendingIntent);
Add receiver in manifest:
<receiver
android:name=“TestReceiver"
<intent-filter>
<action android:name="filter.test.time” />
</intent-filter>
And receiver class as:
class TestReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(AppConstants.FILTER_TESTING))
{
// code here
}
}
}
Why dont you try Time Changed Receiver instead of service, Since using a background service is bad programming approah.A service keeps on running in background and takes a lot of system memory and a burden battery. Moreover system can stop any of extra services running at anytime for adjustment of memory issues.
A time change receiver is the best approach and in that you can compare time and open any app accordingly.
i suggest you this two ways:
Use the "new" ScheduledThreadPoolExecutor as replacement for Timer
Example:
int threadCount = 1;
ScheduledThreadPoolExecutor service = new ScheduledThreadPoolExecutor(threadCount);
long initialDelay = 5;
long period = 10;
ScheduledFuture<?> task = service.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// DO IT EVERY 10 SECONDS
}
}, initialDelay, period, TimeUnit.SECONDS);
[...]
//if you want you can cancel the task later
task.cancel(true); // mayInterruptIfRunning = true
Since Activities, Threads and Processes can be terminated anytime by Android OS it is not guaranteed that the job is always executed.
Therefore, it is better to use AlarmManager
Official howto: Scheduling Repeating Alarms
Another nice example: Repeat Alarm Example In Android Using AlarmManager