I need to have a periodic polling mechanism to detect new orders (after the last order the user has seen) for which
I have setup a couple of broadcast recievers(one for boot activate,and other for executing recurring task) and a service.I use Alarmmanager to periodically call the PeriodicTaskReciever.
Now I need to know how to communicate with such a remote broadcast reciever(A flag parameter indicating the last user seen order needs updation). I've tried shared preferences and as indicated in a lot of articles remote process is unable to read updated values of SP
<service android:name=".OrderService" />
<receiver android:name=".BootReciever" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
<receiver android:name=".PeriodicTaskReciever"
android:process=":remote"
/>
My PeriodicTask Reciever is
public class PeriodicTaskReceiver extends BroadcastReceiver
{ private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
static int lastOrder;
int NOTIFICATION_COUNTID=100;
public void onReceive(final Context context, Intent intent)
{
Log.d("DataHandlerService", "Service hbeat");
if(intent.getIntExtra("update",0)!=0){
lastOrder=intent.getIntExtra("update",0);
Log.d("DataHandlerService", "Last order updated");
}
else{
if(Utils.isNetworkAvailable(AppController.getInstance().getApplicationContext())){
Uri.Builder uri = new Uri.Builder();
uri.scheme("http");
uri.authority(Constants.URL_API_HOST);
uri.path(Constants.URL_API_ORDERPATH);
uri.appendQueryParameter("lastorder",getLastOrderFromSharedPref());
String url=uri.build().toString();
Log.d("DataHandlerService", "Service hbeat"+url);
JsonObjectRequest jsonObjectRequest=new JsonObjectRequest(url,null,new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject jsonObject) {
try {
if(!jsonObject.isNull("status") && jsonObject.getString("status").equals("success")){
if(Integer.parseInt(jsonObject.getString("data"))>0){
displayNotification("You have "+ Integer.parseInt(jsonObject.getString("data"))+ " new orders ",context);
}}
} catch (Exception e) {
}
}
},new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
}
});
AppController.getInstance().addToRequestQueue(jsonObjectRequest,"PollOrders");}}
}
public void SetAlarm(Context context)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, PeriodicTaskReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 , pi); // Millisec * Second * Minute
}
public void CancelAlarm(Context context)
{
Intent intent = new Intent(context, PeriodicTaskReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
Am I misusing the remote. I need to notify users pretty much from the background when my app isnt running. And once the users click on a notification or dismiss it the lastOrder value gets updated.
There is no work of android:process=":remote" for a BroadcastReceiver. So remove that and here you are no using intent-filter for receiver so you need to export that BroadcastReceiver.
Instead of doing
<receiver android:name=".PeriodicTaskReciever"
android:process=":remote"
/>
export your receiver. like
<receiver android:name=".PeriodicTaskReciever"
android:exported="true"
/>
Related
I'm attempting to make it so my app runs some code once per day at 6AM. This works just fine when the app is open and in the foreground, but if the app is closed by swiping it away, the code is never called at the appropriate time.
AlarmReceiver.java (For testing purposes, I have it just trying to display a Toast to verify it runs)
public class AlarmReceiver extends BroadcastReceiver {
public static final String intentAction = "com.mpagliaro98.action.NOTIFICATIONS";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(intentAction)) {
Toast.makeText(context, "RECEIVER CALLED", Toast.LENGTH_LONG).show();
}
}
}
MainActivity.java (Where the alarm is being set)
public class MainActivity extends AppCompatActivity {
...
private void setRecurringAlarm() {
// Set this to run at 6am
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getDefault());
updateTime.set(Calendar.HOUR_OF_DAY, 6);
updateTime.set(Calendar.MINUTE, 0);
updateTime.set(Calendar.SECOND, 0);
updateTime.set(Calendar.MILLISECOND, 0);
// Build the pending intent and set the alarm
Intent i = new Intent(AlarmReceiver.intentAction);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(),
0, i, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
assert am != null;
am.setRepeating(AlarmManager.RTC, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
}
}
AndroidManifest.xml (Just the relevant parts)
<uses-permission android:name="android.permission.SET_ALARM" />
<receiver
android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.mpagliaro98.action.NOTIFICATIONS" />
</intent-filter>
</receiver>
I've read through dozens of similar problems to this on this site and elsewhere and I'm seriously at a loss for why this won't work. Any help would be appreciated.
Try changing receiver to
<receiver android:process=":remote" android:name="AlarmReceiver"></receiver>
Should I use android: process =":remote" in my receiver?
I have done an app as tutorial to learn how to restart deleted alarms after phone is rebooted. After reboot BroadcastReceiver receives BOOT_COMPLETED action and launches a service, which restarts all alarms. Alarms create notification when they are called. After first tests I have received notifications at expected time and then forgot about this tutorial app and didn't turn the phone off.
However, I'm still getting notifications on my screen as if the app has restarted alarms again. During the day I have received twice and all of them are unclear why. The only thing that may launch the restarting alarms is BOOT_COMPLETED action. What's going wrong here?
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.marat.recyclerviewtutorial">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
// list of activities
<service android:name=".BootService"/>
<receiver android:name=".AlarmBroadcastReceiver"/>
<receiver android:name=".RestartAlarmsReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
RestartAlarmsReceiver.java
public class RestartAlarmsReceiver extends BroadcastReceiver {
private static final String TAG = "myTag";
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent i = new Intent(context, BootService.class);
ComponentName service = context.startService(i);
if (null == service) {
// something really wrong here
Log.e(TAG, "Could not start service ");
}
else {
Log.e(TAG, "Successfully started service ");
}
} else {
Log.e(TAG, "Received unexpected intent " + intent.toString());
}
}
}
BootService.java
public class BootService extends Service {
private static final String TAG = "myTag";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
Database db = new Database(this);
db.open();
ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>>();
data = db.getData();
db.close();
Log.d(TAG, "db is openned");
for (int i=0; i<data.size(); i++) {
Intent notif = new Intent(this, AlarmBroadcastReceiver.class);
notif.putExtra("Text", data.get(i).get(2));
notif.putExtra("Position", data.get(i).get(0));
int sec = Integer.parseInt(data.get(i).get(3));
Log.d(TAG, "intent is openned");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, Integer.parseInt(data.get(i).get(0)), notif, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (sec * 1000), pendingIntent);
Log.d(TAG, "Alarm is restarted");
}
Log.d(TAG, "before returning service");
return Service.START_STICKY;
}
}
It's already huge portion of code. But if you will need other parts of my app I will include them.
Thanks in advance!
I think this is because of START_STICKY. I think during the day the system closes your running Service to free resources, and START_STICKY forces it to restart. And on restart onStartCommand() is triggered again.
The decision may to use IntentService instead. I don't see the need of using Service here.
here is my manifest
<receiver android:name=".MyCallReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
and
public class MyCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
some code
}
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE) || intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
some code
}
}
}
it is works but after sometime that press back button and phone be idle it doesn't work any more
(i added "android.os.Process.killProcess(android.os.Process.myPid());" at the end of my code and now it is better and work for maybe 2 3 hour after last execute)
You can use alarm manger to broadcast receiver after certain interval of time like this.
public static void scheduleTestAlarmReceiver(Context context) {
Intent receiverIntent = new Intent(context, TestAlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 123456789, receiverIntent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+startDelay, someDelay, sender);
}
I have 3 applications that are dependent on each other. for instance, Client app, Browser and launcher. My requirement is when the client is uninstalled(only when the client) i want the other two apps to be uninstalled as well. For this what i have done so far is, i have written a broadcast receiver(in both the apps) that listens for package removed. if the package removed is my client, i start an alarm that launches the uninstall procedure(individually on both apps). Why the alarm? because i want the uninstall pop up to come up til the user uninstalls the app. The issue i am currently facing is that, sometimes the launcher app does not get the broadcast or so i think. and hence it does not initiate the uninstall. Sometimes it does and sometimes it doesn't. I am not able to figure out the cause of this problem. below is the code written in the launcher:
The broadcast receiver :
public class UnistallBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
String packagename = intent.getData().getSchemeSpecificPart();
if (packagename.equalsIgnoreCase("com.android.nanoheal")) {
Calendar calendar = new GregorianCalendar();
calendar.setTimeZone(TimeZone.getDefault());
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 00);
Intent intent1 = new Intent(context, AlarmIntent.class);
intent1.putExtra("appnamel", "com.nanoheal.launcher");
PendingIntent pi = PendingIntent.getBroadcast(context, 325,
intent1, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 1000 * 30, pi);
}
}
}
}
the Alarm Intent:
public class AlarmIntent extends BroadcastReceiver {
Context mContext;
#Override
public void onReceive(Context context, Intent intent) {
Log.d("AlarmIntent", "Intent fired by Launcher");
mContext = context;
try {
String appLauncher = intent.getStringExtra("appnamel");
if (appLauncher != null) {
if (isAppInstalled(appLauncher)) {
Uri packageURI2 = Uri.parse("package:" + appLauncher);
Intent uninstallIntent2 = new Intent(
Intent.ACTION_UNINSTALL_PACKAGE, packageURI2);
uninstallIntent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(uninstallIntent2);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean isAppInstalled(String packageName) {
PackageManager pm = mContext.getPackageManager();
boolean installed = false;
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
installed = true;
} catch (PackageManager.NameNotFoundException e) {
installed = false;
}
Log.d("AlarmIntent", "Launcher-IsAppInstalled " + packageName + " "
+ installed);
return installed;
}
}
I am not very certain about the details of how and why.
But i changed this
<receiver android:name="package.UnistallBroadcast" >
<intent-filter android:priority="1000">
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
to
<receiver android:name="package.UnistallBroadcast" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
and it worked fine. As far as i know if the priority is set for a receiver the one with the highest priority should get the action first. but strangely, in my case i was not getting the action for the receiver i gave priority.
I HAVE to be missing something, I made a test Application Project for myself and this works perfectly there but when I tried to implement my AlarmManager into my main project's fragment it just won't work. Here's my code:
The Method that is in my fragment:
public void schedule()
{
Long time = new GregorianCalendar().getTimeInMillis()+10*1000;
Intent intent = new Intent(getActivity(), AlarmReceiver.class);
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, time, 10*1000, PendingIntent.getBroadcast(getActivity(), 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
and here is my AlarmReceiver.class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
}
And also here are the preparations in my Manifest file:
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
<application
... >
<receiver android:name=".AlarmReceiver"/>
What am I doing wrong?
Note: It seems that it doesn't even reach the AlarmReceiver
Your code seems to work.
But it the problem is the manifest. the
<receiver android:name=".AlarmReceiver"/>
should be the with the full package name, for example
<receiver android:name="com.example.AlarmReceiver"/>
I've double check it with my app. so you are good to go.
You are using the receiver incorrectly. What you need to do first is to add an action to your receiver's manifest
<receiver android:name=".AlarmReceiver">
<intent-filter>
<action android:name="com.example.action.ALARM" />
</intent-filter>
Then, construct the intent with that action:
public void schedule() {
Long time = new GregorianCalendar().getTimeInMillis()+10*1000;
Intent intent = new Intent("com.example.action.ALARM");
...
}
and in your receiver:
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.example.action.ALARM")
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_LONG).show();
}
This should do the trick.