I'm trying to make my android app poll the server for new messages using the example code in this blogpost. I managed to copy paste everything in my project. When I run my project however, it doesn't seem to do anything.
So I've got a PollingService class in a separate file (full code here) in which I tested whether it even gets called using the following constructor:
public class PollingService extends Service {
public void PollingService() {
Log.wtf("I AM ACTUALLY RUNNING", "IN THE Constructor!!!!");
}
I try to call the PollingService using the following onResume from within my mainActivity:
public void onResume() {
super.onResume();
int seconds = 3;
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, PollingService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
alarmManager.cancel(pendingIntent);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + seconds*1000, seconds*1000, pendingIntent);
}
Does anybody know why the PollingService doesn't run? All tips are welcome!
As I see from the code posted, the service is declaring a void method, not a constructor and that's probably the reason why you won't see the log.
Try:
public class PollingService extends Service {
public PollingService() {
super("PollingService");
Log.v("PollingService", "constructor");
}
...
}
Related
I am getting a problem with my reminder APP.
When I add first reminder broadcast is received once for second time broadcast is received twice for third time it is received thrice.
I tried many different solutions on StackOverfolow but none of them are working
Kindly help me out with detailed answer.
Link to Project
. code is given below:
Function to set Reminder:
public void startAlarm(Calendar c) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlertReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, number, intent, PendingIntent.FLAG_ONE_SHOT);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
}
Class receiving Broadcast:
public class AlertReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, intent.getAction(), Toast.LENGTH_LONG).show();
MediaPlayer mediaPlayer = MediaPlayer.create(context, Settings.System.DEFAULT_NOTIFICATION_URI);
mediaPlayer.start();
}
}
I see that you are setting the alarm inside Adapters onBindViewHolder. This is not the right place to setting alarm. Because when you call notifyDataSetChanged it will call onBindViewHolder again and it will set same alarm over and over.
I want my Android app to periodically update its UI based on the response from a REST service. I can't do this on the main thread because it's not permitted / bad practice to access the network on the main thread. The general wisdom on SO and the internet is to use a combination a BroadcastReceiver and AlarmManager. For example this is the advice here. I've tried two designs, neither of which I can make to work:
Define a class extending BroadcastReceiver as an inner class of my MainActivity.
Define the same class as an outer class.
With (1) I get this runtime error:
java.lang.RuntimeException: Unable to instantiate receiver com.dbs.alarm.MainActivity$AlarmReceiver: java.lang.InstantiationException: java.lang.Class<com.dbs.alarm.MainActivity$AlarmReceiver> has no zero argument constructor
With (2) the problem is I can't figure out how to access the view I want to modify in MainActivity.
Here is an example implementation of (1):
package com.dbs.alarm;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
// I tried making this its own class, but then findViewById isn't accessible.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// I tried wrapping this in runOnUiThread() but it made no difference.
TextView myTextView = findViewById(R.id.my_text);
CharSequence myCharSequence = "Set from UpdateReceiver.onReceive()";
myTextView.setText(myCharSequence);
}
}
private void setRecurringAlarm(Context context) {
Intent intent = new Intent(context, AlarmReceiver.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000,
1000, // Set so short for demo purposes only.
pendingIntent
);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRecurringAlarm(this);
}
}
I also added this to my AndroidManifest.xml, and considering that I get an exception it seems to be registered successfully:
<receiver android:name="com.dbs.alarm.MainActivity$AlarmReceiver">
</receiver>
Since you need direct access to your text view, choosing an inner class for your receiver was the right thing to do. However, BroadcastReceivers that are declared as inner classes must be static to be declared in the manifest, which defeats the purpose of making it an inner class in the first place (in your scenario, at least). Because of this, I suggest registering/unregistering your BroadcastReceiver dynamically in the onStart() and onStop() lifecycle methods:
public class MainActivity extends AppCompatActivity {
private BroadcastReceiver alarmReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// the "MainActivity.this" tells it to use the method from the parent class
MainActivity.this.updateMyTextView();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setRecurringAlarm(this);
}
#Override
protected void onStart() {
super.onStart();
final IntentFilter filter = new IntentFilter();
filter.addAction("YOUR_ACTION_NAME");
registerReceiver(alarmReceiver, filter);
}
#Override
protected void onStop() {
unregisterReceiver(alarmReceiver);
super.onStop();
}
private void updateMyTextView(){
final TextView myTextView = findViewById(R.id.my_text);
if (myTextView != null){
CharSequence myCharSequence = "Set from UpdateReceiver.onReceive()";
myTextView.post(()-> myTextView.setText(myCharSequence));
}
}
private void setRecurringAlarm(Context context) {
Intent intent = new Intent("YOUR_ACTION_NAME");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 1000,
1000, // Set so short for demo purposes only.
pendingIntent
);
}
}
You'll also notice that rather than pass in the receiver class when creating the intent for the alarm, I changed it to use a string ("YOUR_ACTION_NAME") that you can use to define the intent filter your BroadcastReceiver will use to listen for broadcasts.
As for the issue of running the updates on the UI thread, you can always call post() from a view to run something on the UI thread, or use an activity's runOnUiThread like you attempted to do within the BroadcastReceiver. I made the "update" method belong to the activity rather than the broadcast receiver, since it seemed to make more sense that way in my head.
EDIT: When writing this answer, I was more focused on solving the issues you were encountering while implementing your solution rather than actually trying to help solve the larger problem of performing periodic UI updates. #Ashikee AbHi's suggestion of using a Handler for this rather than alarm is definitely something you should consider. An alarm/broadcast receiver is great when you have to notify something in a different process, but if everything is contained in a single activity, it would be much cleaner to use Handler.postDelayed.
You can user Handler and call it recursively to perform periodic operations.Check the following
Repeat a task with a time delay?
If updating view you need to initialize it with new Handler(Looper.getMainLooper())
In the simplest way you have to run REST request in the background thread like an AsyncTask doInBackground and send result of the request to UI-thread in onPostExecute. You can do that by means of different ways, but the most convinient for me is a usage of Bus'es, for example Otto.
Okay so looking at your requirement I would say that you're fetching some data and you want to let your app know that new data has been fetched so the app can make the necessary UI changes. I would suggest using a Local Broadcast Manager , it allows you to send broadcasts within your app.
The implementation can be found pretty easily, you can check this out.
Basically the idea is you fetch data from the REST API, broadcast to your app that data has been fetched and every activity that needs to respond to this event will have a receiver that will get notified.
I have an Android background service that report positions from time to time. When I test locally over wifi it works pretty well, however when testing in 3G connection for example (sometimes on Edge) I have perceived that the application apparently enters in a bottleneck and do not execute the onLocationChanged method. That's okay because maybe lost signal or so on. However after a while (maybe when connection is re-established) it start updating all requests at once, in a matter of a few seconds many many times the method onLocationChanged is executed.
Does anyone have ideas how to solve that? Is it possible to add timeout into the method locationManager.requestLocationUpdates?
My Listener
public class MyListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
//report location to server
HttlCallToUpdatePostion(loc.Latitude, loc.Longitude, loc.Accuracy);
}
}
My Service
Handler handler = null;
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
MyListener listener = new MyListener();
protected void doWork() {
Looper.prepare();
handler = new Handler();
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, listener);
Looper.loop();
}
I wrote an app, exactly what you need.
When it was a service only I met the same problem. While the UI went to background and screen off the service went to background and it scheduled the system calls, once when triggered the buffer was flushed and I had like 10-50 updates.
The solution it is: an Alarm must be set and scheduled with 5000 value and a BroadcastRreceiver will receive and it will handle properly. Than you will meet other problems, which is not asked here.
For me this was a SOLUTION and the app is in use!
Edit:
Alarm setup code part:
Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
// In reality, you would want to have a static variable for the request
// code instead of 192837
PendingIntent sender = PendingIntent.getBroadcast(this, 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the AlarmManager service
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
// am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
am.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), timerInterval, sender);
AndroidManifest.xml :
<receiver android:process=":remote" android:name=".broadcastreceiver.AlarmReceiver"/>
class implementation part:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Context appContext = context.getApplicationContext();
...
check for power saving mode in adorid system setting: it must be disable to permit location manager to generete update location when the screen is off
I have an application in which I have to call off an alarm/notification each 30 Minutes.
I want the feature like
1- If app is closed, it open the app, Call a dialog box. On click it will call a serverFunction and if MainActivity is running, update its UI.
2- If the app is already opened , Call a dialog box. On click it will call a serverFunction. Since MainActivity is may or may NOT on the top, update its UI Or NOT.
In My MainActivity.class
private void callNotification()
{
AlarmManager service = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(this, AlarmReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(this, 0, i,PendingIntent.FLAG_CANCEL_CURRENT);
Calendar time = Calendar.getInstance();
time.setTimeInMillis(System.currentTimeMillis());
time.add(Calendar.SECOND, Constants.TIME_CONSTANT);
service.set(AlarmManager.RTC_WAKEUP ,time.getTimeInMillis(), pending);
}
public class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(final Context context, Intent intent)
{
}
}
The problem here is , I can't put a dialog box in onReceive since context is not Activity context. What If the app is opened , Now how am I suppose to implement above features.
In your onReceive place this to call your activity:
Intent i = new Intent(context, AlertActivity.class);
i.setFlags
startActivity(i);
Once you are in your activity you can open up a dialog.
I recommend you use a different activity than your main one to handle displaying the alert, as it makes sense from a design standpoint and it also makes implementation easier. Remember you can make Activities look like dialogs...
In my application, I've got an alarm which triggers a service which downloads information from the internet and shows a notification.
Here's a simplified version of my code:
MyActivity contains this:
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 20);
Intent intent = new Intent(this, AlarmService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 20000, pendingIntent);
And AlarmService looks like this:
public class AlarmService extends Service {
#Override
public void onCreate() {
new myAsyncTask().execute();
}
private class myAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... args) {
//Download stuff
return null;
}
#Override
protected void onPostExecute(Void arg) {
//Show notification
}
}
}
I don't really understand when to use wake-locks, so my question: in this case, should I use a wake-lock and if so, where should I start and stop it?
Thanks in advance
Yes, you will need to use a WakeLock to ensure that your service can finish its work.
If using an IntentService meets your design requirements, I would take a look at WakefulIntentService. It manages the alarms and the WakeLocks on your behalf and is easy to set up. The WakeLock is acquired when the alarm fires, and the WakefulIntentService library takes care of releasing it when the service is finished.
If you go this route, you won't want to use AsyncTask -- you'll need to keep the service actively busy (in its doWakefulWork() method) in order to hold the WakeLock.