I am new to android. I what to know the difference between Intent and BroadcastReceiver. I am more confused with BroadcastReceiver than Intent.
Please help me out. Simple code will be helpful.
Ok, I will explain it with an example.
Let's suppose I want to create an app to check subway status from it's webpage. I also want a system notification if the subway is not working ok.
I will have:
An Activity to show results.
A Service to check if the subway is working and show a notification if it's not working.
A Broadcast Receiver called Alarm Receiver to call the service every 15 minutes.
Let me show you some code:
/* AlarmReceiver.java */
public class AlarmReceiver extends BroadcastReceiver {
public static final String ACTION_REFRESH_SUBWAY_ALARM =
"com.x.ACTION_REFRESH_SUBWAY_ALARM";
#Override
public void onReceive(Context context, Intent intent) {
Intent startIntent = new Intent(context, StatusService.class);
context.startService(startIntent);
}
}
Explanation:
As you can see you can set an alarm. and when the alarm is received we use an intent to start the service. Basically the intent is a msg which can have actions, an serialized stuff.
public class StatusService extends Service {
#Override
public void onCreate() {
super.onCreate();
mAlarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intentToFire = new Intent(AlarmReceiver.ACTION_REFRESH_ALARM);
mAlarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);
}
#Override
public void onStart(Intent intent, int arg1) {
super.onStart(intent, arg1);
Log.d(TAG, "SERVICE STARTED");
setAlarm();
Log.d(TAG, "Performing update!");
new SubwayAsyncTask().execute();
stopSelf();
}
private void setAlarm() {
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
mAlarms.setInexactRepeating(alarmType, SystemClock.elapsedRealtime() + timeToRefresh(),
AlarmManager.INTERVAL_HALF_DAY, mAlarmIntent);
}
}
Explanation:
The service starts and:
Set the alarm for the next call. (Check the intent it's used. Just a msg)
Calls an AsyncTask which takes care of updating an notifying the Activity
It doesn't make sense to paste the AsyncTask but when it finished it calls:
private void sendSubwayUpdates(LinkedList<Subway> subways) {
Intent intent = new Intent(NEW_SUBWAYS_STATUS);
intent.putExtra("subways", subways);
sendBroadcast(intent);
}
This creates a new Intent with a certain NEW_SUBWAYS_STATUS action, put inside the intent the subways and sendBroadcast. If someone is interested in getting that info, it will have a receiver.
I hope I made myself clear.
PS: Some days ago someone explained broadcast and intents in a very cool way.
Someone wants to share his beer, so he sends a broadcast
with an intent having action:"FREE_BEER" and with an extra: "A glass of beer".
The API states:
A BroadcastReceiver is a base class for code that will receive intents sent by sendBroadcast().
An intent is an abstract description of an operation to be performed.
So, a BroadcastReceiver is just an Activity that responds to Intents. You can send your own broadcasts or even the Android Device can send these system wide broadcasts including things like the battery is low, or the device just booted-up.
Related
Having quite a bit of trouble getting my foreground service to simply dismiss on swipe or by the clear all notifications button. I know there are several questions like this, but I have read them and will list some of what I've already tried. I tried this method, where you pass a simple intent with an extra into a pending intent, then add that pending intent to setDeleteIntent(). That didn't work, it never gets called.
I also tried this (second highest answer, "fully fleshed out" version), with the same results. Which ties in to the "answer" of this question as well. With how many apps have notifications that are dismissible with a swipe or clear all button, I must be missing something very obvious and I can't figure out what.
What my current code looks like (all of this inside of my service class).
BroadcastReceiver class
public class NotificationDismissedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this is never called
stopSelf();
}
}
// in the manifest for that BroadcastReceiver, have also tried it with these values false
android:exported="true"
android:enabled="true"
Pending intent
private PendingIntent createOnDismissedIntent(Context context, int notificationId) {
Intent intent = new Intent(context.getApplicationContext(), NotificationDismissedReceiver.class);
PendingIntent pendingIntent =
PendingIntent.getBroadcast(context.getApplicationContext(),
notificationId, intent, 0);
return pendingIntent;
}
In the notification builder (101 is what I startForeground with)
.setDeleteIntent(createOnDismissedIntent(this, 101))
Edit:
Separate file receiver used instead of the inner class version.
public class NotificationDismissedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int notificationId = intent.getExtras().getInt("notificationId");
/* Your code to handle the event here */
if(notificationId == 101){
Intent stopIntent = new Intent(context, AssistorServiceClass.class);
context.stopService(stopIntent);
}
}
}
Edit2
To be clear, I'm not trying to stop the foreground notification and keep the service alive. I want them both just gone, as if I called stopSelf within the service class.
i like to know is there way to execute code in system app process in android.
i found through pending intent we can assign our job to execute in foreign application like alarm manager or notification but still i found job gets execute in same application process .for clear understanding
Here i'm creating alarm manager on buttonclick event.
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Log.d("processstatus", "pid="+android.os.Process.myPid());
//creating an alarm manager
alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, customreciever.class);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,SystemClock.elapsedRealtime() +10*1000, pendingIntent );
}
});
Through below code, i receive the broadcast event which gets triggered every interval of 10 sec through alarmmanager.
public class customreciever extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
// Same app process id expecting alaramanager process id
Log.d("processstatus", "pid="+android.os.Process.myPid());
}
}
inside onReceive method i expect different process id other than application process.if this is not possible through pending intent,suggest me any other approach to achieve this.
You cannot run code in a system process. That would be a huge security hole.
Using a PendingIntent lets you delegate the triggering of code to another user/process/application, but the code still runs in your application with your user ID and your permissions.
At point A in my application I start my service and expect the service get closed from point B. However, there might be few scenarios that point B doesn't ask service to get closed. In this case I want the service close itself after fixed amount of time.
I have written following code into my Service class and expect the service gets closed after 10 seconds from launch time (It will be 45min in the future but I don't want to stay that long for test).
public class ChatService extends Service implements ITCPConnection
{
private static final int SERVICE_LIFE_TIME = 10 * 1000; // In millis
private AlarmReceiver mAlarmReceiver;
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
#Override
public void onCreate()
{
super.onCreate();
//
mAlarmReceiver = new AlarmReceiver();
registerReceiver(mAlarmReceiver, new IntentFilter());
//
Intent intent = new Intent(this, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + SERVICE_LIFE_TIME, alarmIntent);
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.e(TAG, "onDestroy()");
// Unregister receiver
if (mAlarmReceiver != null)
{
unregisterReceiver(mAlarmReceiver);
}
disconnect();
}
public void disconnect()
{
// If the alarm has been set, cancel it.
if (alarmMgr!= null)
{
alarmMgr.cancel(alarmIntent);
}
...
Log.e(TAG, "disconnect()");
}
/*****************
* Alarm Receiver
*****************/
private static class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.e(TAG, "Stop service from AlarmReceiver");
context.stopService(intent);
}
}
}
My problem is AlarmReceiver.onReceive() never gets called and therefore my service will be alive indefinitely.
What you are trying to do is to targeting a broadcast receiver explicitly.
According to this, it cannot be done over a dinamically created (i.e. not declared into the manifest) broadcast receiver, because the os would not know how to resolve it.
To check if this is the root of the problem, you can go with the implicit way and set an action inside the intent and by filtering it in the IntentFilter.
Anyway, using the post delayed can be seen as a valid alternative, since you expect the service to be shut down naturally or still be around to intercept the delayed event.
Another (unrelated) thing is that you are calling
context.stopService(intent);
by using the broadcast intent and not the intent that started the service. You could simply call stopSelf().
I want to make a service in android which run in background always and start as soon as I boot my phone and send message at a regular interval.I have writen my code as below
MainActivity.class
package test.sai;
public class MainActivity extends Activity {
Timer t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
alrm();
Log.e("msg", "in main");
}
public void alrm() {
Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
Log.e("msg", "in alrm");
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = v PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
Log.e("msg", "in alrm1");
//updateTime.setWhatever(0);
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, recurringAlarm); //you can modify the interval of course
}
}
This class is calling AlarmReceiver.class
package test.sai;
public class AlarmReceiver extends BroadcastReceiver
{
GPSTracker gps;
#Override
public void onReceive(Context context, Intent intent)
{
gps = new GPSTracker(context);
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context,MainActivity.class);
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(pushIntent);
Log.e("pro", "alrmmanager");
}
Intent myService = new Intent(context, FirstService.class);
myService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(myService);
Log.e("msg", "in alrmmanager1");
}
}
and finally AlarmReceiver is calling the service class
package test.sai;
public class FirstService extends Service{
Timer t;
int time = 0;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onStart(Intent intent, int startId) {
Log.e("time", time++ +"");
Toast.makeText(this, time+1+"", 500).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
Now I want to on GPS as soon as service starts and then I want to use GPS to track location of mobile and send a message to another mobile.I also have code for GPS and sms sending but I am not getting how to call and where to call those methodss,so that my service keep on running and sending messages at some perticular interval.please help.
You can use alarmManager for this... Because if you create your own timerTask, it is very much susceptible to get destroyed by the processor.
To answer your two part question:
First you need to learn how to handle onBoot within Android Framework. Refer to this Q/A Trying to start a service on boot on Android
Lastly you need to understand the SMSManager class. Refer to the documentation http://developer.android.com/reference/android/telephony/SmsManager.html
I don't think anyone should provide complete code for your request as your main problem/question is "How can I help myself and stop looking for others to fix all my problems".
Try registering a BroadcastReceiver with AlarmManager to receive an intent at your regular interval. You'll probably want two, one that listens for a BOOT_COMPLETED action, and another that the AlarmManager will start on interval. You can have the second receiver start a service if whatever you want to do will take a while to execute.
Here's a question on how to make the receiver run on boot so you can register the other receiver with AlarmManager:
Android BroadcastReceiver on startup
Here's another that wants pretty much the same thing you want, minus the SMS:
How to Autostart an AlarmManager to start a Scheduled Activity?
I have scheduled multiple alarm managers to send intents at different times.
I took care to pass unique ID, context and extras to both the pending intents.
below func handles the alarm calls.
.
public void handle(int duration, int id){
Intent intent = new Intent("package.SET");
intent.putExtra ("package.id", Id);
AlarmManager amg = (AlarmManager)Context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pis = PendingIntent.getBroadcast(Context,Id, intent, FLAG_ONE_SHOT);
amg.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + time, pis); }
there are 2 functions calling the alarm
public void callalarm(int time){
handle(time, UNIQUE_ID1);}
and
public void callalarm2(int time){
handle(time, UNIQUE_ID2);}
I took care that unique ID1 and Unique_ID2 are different.
The broadcast receiver handles the alarm and executes another code.
Is there a possibility that Callalarm1 and callalarm2 interfere with eachother .
I have registered the receiver using registerReceiver function and not in android manifest file.
IntentFilter ARFilter = new IntentFilter();
ARFilter.addAction("package.SET");
context.registerReceiver(AR, ARFilter);
In the AR that extends broadcast receiver, i use the id to define the action.
public BroadcastReceiver AR= new BroadcastReceiver()
{ public void onReceive(Context context, Intent intent)
{ // i do some stuff here which is confidential
}}
The problem is that, I get a delay in the alarms. Is there a reason why there is a delay ?
As of What I know, The Alarm MAnager cannot fire at right times when the task burden on the processor is heavy.
In other words, the broadcast receiver does not receive intent on time since the alarm manager adds the broadcast to the queue which is sent with some delay..
Precise information is helpful.