Currently i can only send the data to the server when my app (activity) is in foreground. This happens at least in 4.1.3 because the android SO pauses the app or stops it.
I need to send data all the time even if the activity is in background.
What is the best way of achieving this. Asynctask is not a good answer because i want to send data periodically. Not once. I already use asynctasks as a way to send the data to the server what i need is something that runs together with the activity but doesn't get stopped by the SO.
EDIT:
I got this error using the below code.
04-03 13:55:28.804: E/AndroidRuntime(1165): java.lang.RuntimeException: Unable to instantiate receiver main.inSituApp.BootCompletedIntentReceiver: java.lang.ClassNotFoundException: main.inSituApp.BootCompletedIntentReceiver
Can anyone tell me what that error means? i dont have a class with that receiver but i though if i register it in the manifest i wouldn't need it.
You can write services and AlarmManager to do so. Simply register your application in services and call alarmMangaer.setRepeat() method to start your code of serverside or any other operation you want to do in onStart() method of services
public class MyService extends Service{
Calendar cur_cal = Calendar.getInstance();
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Intent intent = new Intent(this, MyService.class);
PendingIntent pintent = PendingIntent.getService(getApplicationContext(),
0, intent, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
cur_cal.setTimeInMillis(System.currentTimeMillis());
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cur_cal.getTimeInMillis(),
60 * 1000*3, pintent);
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
// your code for background process
}
}
Add this in AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<service
android:name="com.yourpackage.MyService"
android:enabled="true" />
<receiver android:name=".BootCompletedIntentReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Edit:
BootCompletedIntentReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootCompletedIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context, MyService.class);
context.startService(pushIntent);
}
}
}
Related
i am using AlarmManager class for setting Alarms it is working fine.
But if i set alarm like 9pm and current time is 8pm and i changed the system time to 10pm
then alarm 9pm alarm start automatically. so to solve this issue
i have searched so much but did not found any good answer
Please help
here is my code for alarm setting
final int id = (int) System.currentTimeMillis();
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("requestCode", id);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 2*60*1000, pendingIntent);
One of the options is to store all set alarms in database, then create a BroadcastReceiver which will listen for ACTION_TIME_CHANGE action. When user changes time it will be triggered. Then create a IntentService which will be responsible for resetting alarms. In this service class:
Read db and identify all passed alarms.
Cancel passed alarms
Set alarms for next day
Your code may look like as below:
In your Manifest:
<uses-permission android:name="android.permission.ACTION_TIME_CHANGE"/>
and below activities:
<receiver android:name=".TimeChangedReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.TIME_SET" />
</intent-filter>
</receiver>
<service android:name=".RestartAlarmsService"/>
Create class "TimeChangedReceiver" inside of which:
public class TimeChangedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if("android.intent.action.TIME_SET".equals(intent.getAction())) {
Intent i = new Intent(context, RestartAlarmsService.class);
ComponentName service = context.startService(i);
}
}
}
Create "RestartAlarmsService" class inside of which:
public class RestartAlarmsService extends IntentService {
public RestartAlarmsService() {
super("RestartAlarmsService");
}
#Override
protected void onHandleIntent(Intent intent) {
// read db here
// then cancel passed alarms
// reset them to next day
}
}
You can find many tutorials on how to use Databases and implement it in your code. Hope my answer is somehow helpful.
yes it will give you broadcast, as your pending intent object is still attached to that event while you change time that is greater than you alarm firing time.
solution- validate your condition while you receive broadcast from alarm manager
How is it possible to send a notification programmatically, when the App got completely closed?
Example: The User closed the App, also in the Android Taskmanager, and waits. The App should send a notification after X Seconds or when the App check for Updates.
I tried to work with these code examples but:
Pushing notifications when app is closed - too many Activities/doesn't work
How do I get my app to send a notification when it is closed? - much information, but I don't know how to deal with it
How to send local notification android when app is closed? - much information, but I don't know how to deal with it
If you can, try to explain it at an example, because beginners (like me) can easier learn it this way.
You can use this service all you need to do is Start this service onStop() in your activity lifecycle. With this code:
startService(new Intent(this, NotificationService.class));
then you can create a new Java Class and paste this code in it:
public class NotificationService extends Service {
Timer timer;
TimerTask timerTask;
String TAG = "Timers";
int Your_X_SECS = 5;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
#Override
public void onCreate() {
Log.e(TAG, "onCreate");
}
#Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
stoptimertask();
super.onDestroy();
}
//we are going to use a handler to be able to run in our TimerTask
final Handler handler = new Handler();
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, after the first 5000ms the TimerTask will run every 10000ms
timer.schedule(timerTask, 5000, Your_X_SECS * 1000); //
//timer.schedule(timerTask, 5000,1000); //
}
public void stoptimertask() {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
//use a handler to run a toast that shows the current timestamp
handler.post(new Runnable() {
public void run() {
//TODO CALL NOTIFICATION FUNC
YOURNOTIFICATIONFUNCTION();
}
});
}
};
}
}
After this you only need to combine the service with the manifest.xml:
<service
android:name=".NotificationService"
android:label="#string/app_name">
<intent-filter>
<action android:name="your.app.domain.NotificationService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
You can use alarm manager to do this [Not tested on latest Android versions and releases and is a pretty old answer].
Follow below steps :
Use alarmmanager to create an alarm of after X seconds.
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("NotificationText", "some text");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, ledgerId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, 'X seconds in milliseconds', pendingIntent);
Use a AlarmBroadCast receiver in your app.
Declare in manifest file :
<receiver android:name=".utils.AlarmReceiver">
<intent-filter>
<action android:name="android.media.action.DISPLAY_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
In the broadcast receiver's on receive, you can create the notification.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// create notification here
}
}
You can check active apps using service and display notification if activity is not running.
Following the answer from Nikhil Gupta and referring to the website provided by Bondolin in the comments, adding the attribute android:process=":remote" to the receiver allowed me to post a notification even when the app is completely closed.
<receiver
android:name = ".utils.AlarmReceiver"
android:process=":remote" > <!-- this line is important -->
</receiver>
And the rest of the code is basically the same. An important thing to note is that the class AlarmReceiver should not contain any reference to the MainActivity, since when the app is closed, the MainActivity class is not instantiated. NullPointerException will be thrown if you attempt to reference MainActivity in the AlarmReceiver class when the app is closed.
I am trying to execute an action once at a later time using AlarmManager. I followed the code and the question here and came up with this.
public class EmailAccountUpdater extends BroadcastReceiver
{
// Constructors
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION))
{
Log.v("Test", " Step 1 - Creating the alarm " );
// Place holder
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent newIntent = new Intent("com.test.EMAIL_ACCOUNTS_CHANGED");
PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, newIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.set( AlarmManager.RTC_WAKEUP, 35000, pendingIntent);
}
}
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver
{
// constructors
#Override
public void onReceive(Context context, Intent intent)
{
Log.v("Test","Step 2 - Alarm received");
if (intent.getAction().equals("com.test.EMAIL_ACCOUNTS_CHANGED"))
{
onAccountsUpdated();
}
}
public void onAccountsUpdated()
{
// do something
}
}
In the manifestManifest.xml
<receiver android:name="full.path.AlarmReceiver">
<intent-filter>
<action android:name="com.test.EMAIL_ACCOUNTS_CHANGED"/>
</intent-filter>
</receiver>
Basically what I wanted to do was to put the following in Placeholder (just below the first log statement).
Thread.sleep(35000);
onAccountsUpdated();
But according to this, it is not suggestible to use postDelayed and Thread.sleep in BroadcastReceiver. So I came up with this. What happens is I always get the Step 1 but never reach the step 2. What I am I doing wrong? Any help would be welcome.
The solution is (as per the thread you linked):
you want something to happen some time after the broadcast you can start a service, and that service wait the amount of time, or if the amount of time you want to wait is longer than a few seconds, you should just put the launch of this service in the AlarmManager and let the AlarmManager launch the service for you.
Your plan doesn't work because the context is destroyed after EmailAccountUpdater.onReceive returns.
I am making an application with a feature of alarms in it. I am using service for this which keeps checking the current time of device against the times in my DB.
My problem is that this service stops if the app removed from the background or if the device is rebooted. I have used START_STICKY to keep it running in background and used a broadcast receiver to start it on reboot.
The major concern is that whatever I have coded is working on a MOTO G device. Reboot, clearing from background, everything, the service is running fine. But in Xiomi phones and Huawei Honour, It stops once cleared from background or rebooted.
The Service code:
public class RemindService extends Service {
final long delayMillis=500;
Handler h=null;
Runnable r;
SharedPreferences sp;
PendingIntent pendingIntent;
private static final int NOTIFY_ME_ID=1337;
#Override
public void onCreate() {
h=new Handler(Looper.getMainLooper());
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags,int startId) {
r = new Runnable() {
public void run() {
//SOME OF MY IF-ELSE CONDITIONS
Intent myIntent = new Intent(RemindService.this, ReminderPopUp.class);
int randomPIN = (int)(Math.random()*9000)+1000;
pendingIntent = PendingIntent.getActivity(RemindService.this, randomPIN, myIntent,PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager)getSystemService(Activity.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC|AlarmManager.RTC_WAKEUP, System.currentTimeMillis() , pendingIntent);
h.postDelayed(this, delayMillis);
}
};
h.post(r);
return Service.START_STICKY;
}
#Override
public void onDestroy() {
h.removeCallbacks(r);
}
}
My Manifest declarations:
<service
android:name="test.aguai.medieazy.RemindService"
android:enabled="true" />
<intent-filter>
<action android:name="test.aguai.medieazy.START_SERVICE" />
</intent-filter>
Has anybody else faced this problem? I think it is a problem of modified OS, but anyways my app is not working properly. Please Help.
Rather than poll the device database constantly, I would make use of the AlarmManager service as I described in this answer:
Android Polling from a Server periodically
Set up the alarm to fire at the first scheduled time. When it fires, set up the next time and so on. There is no need to set up every alarm at once as only one can ever fire at a time.
When the alarm fires, you can start a service to perform whatever task you need (including the setting of the next alarm)
Try Lik this it will Work
// for Every 6 minutes exact repeating service
Intent myIntent2 = new Intent(sign_in.this,MyAlarmService.class);
pendingintent3 = PendingIntent.getService(sign_in.this, 2,myIntent2, 2);
AlarmManager alarmManager2 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar2 = Calendar.getInstance();
calendar2.setTimeInMillis(System.currentTimeMillis());
calendar2.add(Calendar.SECOND, 30);
alarmManager2.set(AlarmManager.RTC_WAKEUP,calendar2.getTimeInMillis(), pendingintent3);
alarmManager2.setRepeating(AlarmManager.RTC_WAKEUP,calendar2.getTimeInMillis(), 360 * 1000,pendingintent3);
manifest permission
<!-- Web data Sync Service -->
<service android:name="com.example.MyAlarmService" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</service>
If you want your service to be running until explicitly stopped then consider calling startService(), to start the service. This allows the service to run indefinitely, and also allow a client to bind to the service by calling bindService().
Remember you must explicitly stop the service, by calling stopSelf() or stopService().
I have a service that autoupdates a database in a given time interval. To do this it gets information from the Internet.
I need to have it unbound, so that It runs over all activities. But when the application is closed, it would be nice to terminate the service. To prevent battery drain. How can this be achieved?
I think that you should let your service be started by a boot broadcastReceiver, then ask AlarmManager to relaunch it every now and then.
public class DbUpdateService extends Service {
//compat to support older devices
#Override
public void onStart(Intent intent, int startId) {
onStartCommand(intent, 0, startId);
}
#Override
public int onStartCommand (Intent intent, int flags, int startId){
//your method to update the database
UpdateTheDatabaseOnceNow();
//reschedule me to check again tomorrow
Intent serviceIntent = new Intent(DbUpdateService.this,DbUpdateService.class);
PendingIntent restartServiceIntent = PendingIntent.getService(DbUpdateService.this, 0, serviceIntent,0);
AlarmManager alarms = (AlarmManager)getSystemService(ALARM_SERVICE);
// cancel previous alarm
alarms.cancel(restartServiceIntent);
// schedule alarm for today + 1 day
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, 1);
// schedule the alarm
alarms.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), restartServiceIntent);
return Service.START_STICKY;
}
}
To start your service at boot time use this :
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class serviceAutoLauncher extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context,DbUpdateService.class);
context.startService(serviceIntent);
}
}
Finally add this to your manifest to schedule your serviceAutoLauncher to be launched at each boot:
<receiver android:name="serviceAutoLauncher">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
<category android:name="android.intent.category.HOME"></category>
</intent-filter>
</receiver>
Use the stopService method.
It depends on how you start the service. If you start it when your Activity is opened, then call stopService in your Activities onDestroy().