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.
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 want to set One time alarm for certain Date and time. And i also set this by using alarm manager. But My problem is when device switch off and switch on then alarm is not wake up.
My code ::
public void setAlarm(String initialTime, String diffTime) throws ParseException {
Calendar cal = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
cal.set(Calendar.DATE,date);
cal.set(Calendar.MONTH,month-1);
cal.set(Calendar.YEAR,year);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, second);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ChatScreen.this, AlarmNotificationReceiver.class);
i.putExtra("CoId", coId);
i.putExtra("DeptId", deptNo);
i.putExtra("CoName", companyName);
i.putExtra("DpLogo", dpLogo);
i.putExtra("DeptName",deptName);
i.setAction("isFromAlram");
PendingIntent pi = PendingIntent.getBroadcast(ChatScreen.this,0, i, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),pi);
}
My AlarmReceiverclass :::
public class AlarmNotificationReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.e("AlarmReceiver",action);
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
Toast.makeText(context, "ALARM_BOOT_COMPLETED", Toast.LENGTH_LONG).show();
} else if (action.equals("isFromAlram")) {
Logger.errorLog("From Service", "yes");
}
}
}
and also give permission in menifest file android:name="android.permission.RECEIVE_BOOT_COMPLETED"
receiver
android:name="com.chatapi.ChatApi.MyBroadcastReceiver"
android:enabled="true"
EDIT Here the complete manifest entry for the receiver
<receiver android:name=".AlarmNotificationReceiver"
android:enabled="true"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="isFromAlram" > </action>
</intent-filter>
</receiver>
You should add logging to see if your BroadcastReceiver is being called on device boot. Using Toast for this is a bad idea, you may never get to see it. Use logging and check your logcat.
Alarms are not preserved over device boots. When the device boots, your BroadcastReceiver should get called. You then need to set the alarm again.
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 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"
/>
I'm working on the app that will start two alarms as the following:
Repeating alarm at every hour once it's started
Non-repeating alarm at either 1 to 10 hours based on the user selection
Both of the alarms are using ELAPSED_REALTIME_WAKEUP type. The problem I'm facing now is that the same codes work fine on Android 2.3.5 but Android 4.0.4. I have done some research on google and the problem doesn't seem to link to the issue of "no broadcast receiver will be triggered until the app is launched manually for the first time".
The following are the codes for setting up the pending intent for both the alarms:
private class AlarmEvent {
private Intent mIntent;
private PendingIntent mPendingIntent;
protected AlarmEvent(Context ctx, Class<?> cls, int pendingIntentType,
int requestCode, int flags, String intentAction) {
mIntent = new Intent(ctx, cls);
mIntent.setAction(intentAction);
switch(pendingIntentType) {
case PENDING_BROADCAST:
mPendingIntent = PendingIntent.getBroadcast(ctx, requestCode, mIntent, flags);
break;
case PENDING_SERVICE:
mPendingIntent = PendingIntent.getService(ctx, requestCode, mIntent, flags);
break;
default:
Log.w(TAG, "AlarmEvent:Invalid pending intent type=" + pendingIntentType);
}
}
protected PendingIntent getPendingIntent() {
return mPendingIntent;
}
}
The following are the codes to create the AlarmEvent:
//Create polling event
mPollingEvent = new AlarmEvent(mCtx, EventRouter.class, PENDING_BROADCAST,
POLLING_REQUEST_CODE, PendingIntent.FLAG_CANCEL_CURRENT,
EventRouter.POLLING_ACTION);
//Create monitor event
mReminderEvent = new AlarmEvent(mCtx, EventRouter.class, PENDING_BROADCAST,
REMINDER_REQUEST_CODE, PendingIntent.FLAG_CANCEL_CURRENT,
EventRouter.REMINDER_ACTION);
The following are the codes to start the alarms:
//Get AlarmManager instance
AlarmManager alarm = (AlarmManager)mCtx.getSystemService(AS);
long triggerAtTime = 0;
//Process the request
switch(type) {
case POLLING:
triggerAtTime = SystemClock.elapsedRealtime();
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime,
POLLING_INTERVAL_MS, mPollingEvent.getPendingIntent());
Log.d(TAG, "alarmRequest:Polling starts at " + System.currentTimeMillis());
break;
case REMINDER:
triggerAtTime = SystemClock.elapsedRealtime() + when;
alarm.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, mReminderEvent.getPendingIntent());
Log.d(TAG, "alarmRequest:Reminder to be fired after " + when + " ms");
break;
}
The following are the codes of the EventRouter:
public class EventRouter extends BroadcastReceiver {
public static final String POLLING_ACTION = "com.xxxxxx.POLLING";
public static final String REMINDER_ACTION = "com.xxxxxx.REMINDER";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "onReceive:Action=" + action);
if(POLLING_ACTION.equals(action)) {
//TODO: Polling handling
}
else if(REMINDER_ACTION.equals(action)) {
//TODO: Reminder handling to fire a status bar notification
}
}
}
The Android manifest for my app:
<application
...
...>
<activity
android:name=".AlarmActivity"
...>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver android:name=".EventRouter" android:enabled="true" android:exported="true"/>
</application>
Both of the alarms are registered properly by executing the following command on terminal:
adb -d shell dumpsys alarm
However, only the POLLING alarm is delivered to my receiver. I have been struggling on this issue for a while and could not find a solution. Can you help to review the way I set up my pending intent to see if there is any mistake?
You should add your actions as an intent filter to your receiver declaration in your manifest file so that it can capture those actions.
<receiver android:name=".EventRouter" android:enabled="true" android:exported="true"
<intent-filter>
<action android:name="your.receiver.package.name.POLLING_ACTION"></action>
</intent-filter>
<intent-filter>
<action android:name="your.receiver.package.name.REMINDER_ACTION"></action>
</intent-filter>
<receiver/>
This is the first mistake that caught my eye.