Service does not run from BroadcastReceiver? - Android - android

I am trying to get my service to run when there is an outgoing call on my phone. But for some reason my service does not run when this happens. I know the code for the "CallReceiver" executes since I used a toast message to display if that runs. I am able to run the service through my main activity, but this means it will run regardless of whether an outgoing call is made....
Below is my code:
The Receiver:
package com.example.hiworld;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class CallReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, CallService.class));
Toast.makeText(context, "Call Receiver started",
Toast.LENGTH_LONG).show();
Log.d("Calling Someone", "onReceived");
}
}
The Service:
package com.example.hiworld;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;
public class CallService extends IntentService {
public long StartTime=0;
public long EndTime =0;
public long TotalTime = 0;
public long NumFreeMins = 0;
public CallService() {
super("CallService");
}
#Override
protected void onHandleIntent(Intent intent) {
StartTime = (System.currentTimeMillis())/60;
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if(tm.getCallState()==0) //getting the time whenever the phone is off
{
EndTime = (System.currentTimeMillis())/60;
TotalTime = EndTime-StartTime;
NumFreeMins = 300-TotalTime;
//notify user
this.displaymsg();
}
}
public void displaymsg()
{
Toast toast = Toast.makeText(getApplicationContext(), ""+NumFreeMins, Toast.LENGTH_SHORT);
toast.show();
}
}
I have seen some people use the line:
context.startService(new Intent(this, CallService.class));
instead of:
context.startService(new Intent(context, CallService.class));
but the latter does not work for me...

Try specifying an <intent-filter> for your IntentService in the manifest for a specific 'action'. Example...
<service
android:name=".CallService" >
<intent-filter>
<action android:name="com.example.hiworld.intent.DO_SOMETHING" />
</intent-filter>
</service>
Then in the onReceive(...) method of your BroadcastReceiver do something like the following...
Intent callReceiverIntent = new Intent("com.example.hiworld.intent.DO_SOMETHING");
// Put the Intent received by the BroadcastReceiver as extras so the
// IntentService can process it...
callReceiverIntent.putExtras(intent);
context.startService(callReceiverIntent);
EDIT:
I built a simple test app based on the code you posted to pasrebin. I kept the code identical for the manifest, receiver and service and simply had to add a default Activity in order to get it to run.
I can see from monitoring logcat in the DDMS perspective of eclipse that the CallReceiver successfully receives the NEW_OUTGOING_CALL Intent and does, in fact, start the CallService.
The problem is, however, with attempting to show a Toast from an IntentService which causes an exception due to a 'leaked handler' and silently crashes.
The reason behind this is that an IntentService uses a background thread to carry out its work and trying to show the Toast (i.e., a UI element) from a non-UI thread won't work as the app has no UI components running. So, regardless of whether you use the local context variable or getApplicationContext(), there simply is no UI context with which to associate the Toast.
The reason why it works when starting the CallService from an Activity is obviously because the Activity provides a UI context that can be used by the Toast. In short, it generally seems that attempting to use Toast from an IntentService isn't a good idea unless the IntentService is always started by a UI component and even then, having a background thread create UI elements (such as a Toast) may cause problems.
The only way that this can be made to work with the current model is to change the IntentService to a Service. By default, code execution of a Service is done on the main (UI) thread and it is quite legal for a Service to show a Toast regardless of whether there are any of the app's Activities showing or not. In fact, I modified the code to use a Service and placed the code from onHandleIntent in onStartCommand() and I can see the Toasts when making an outgoing call.

Try
context.startService(new Intent(context.getApplicationContext(), CallService.class));

Related

Calling peekService from BroadcastReceiver.onReceive returns null if I close the activity

The problem
I wrote a program for Android 4.3, with a main activity, a broadcast receiver and a service. The activity binds to the service in its onCreate method. The activity has a button that schedules an alarm 10 seconds in the future. The alarm triggers the BroadcastReceiver.onReceive. This method attempts to get a hold on the binder, but there is a circumstance in which this fails and peekService returns null.
What works
Clicking the button and waiting 10 seconds
Clicking the button, clicking home, and wait in the home screen till 10 seconds are elapsed.
Clicking the button, clicking the activity list, close the activity by swiping it to the left, reopen the program and wait till 10 seconds are elapsed (you need to be fast :-).
What doesn't work
Clicking the button, clicking the activity list, close the activity by swiping it to the left and wait till 10 seconds are elapsed; this is essentially like (3.) without reopening the program.
Specifically, if I execute these 4 tests I get the following log:
02-05 20:53:29.992: D/ServiceSSCCE.MyService(476): I've been bound.
02-05 20:53:30.179: D/ServiceSSCCE.MainActivity(476): Service connected.
02-05 20:53:43.265: D/ServiceSSCCE.MyReceiver(476): Awesome, let's get this **** done!
02-05 20:53:55.460: D/ServiceSSCCE.MyReceiver(476): Awesome, let's get this **** done!
02-05 20:54:08.531: D/ServiceSSCCE.MyService(764): I've been bound.
02-05 20:54:08.663: D/ServiceSSCCE.MainActivity(764): Service connected.
02-05 20:54:10.890: D/ServiceSSCCE.MyReceiver(764): Awesome, let's get this **** done!
02-05 20:54:23.593: D/ServiceSSCCE.MyReceiver(788): I just received a null binder.
The last message shows that test (4.) failed, while previous messages show that (1.), (2.) and (3.) succedeed.
I'm aware of this, this and this answer, as well as pretty much any relevant result that Google lists in the first two pages. I tried several things, including but not limited to:
Calling startService, both from BroadcastReceiver.onReceive and from the main activity (although I'm not sure I understood how bindService and startService interact)
Fiddling with intents, in particular with context (this VS getApplicationContext and so on).
Setting the service as foreground (see this)
I'm really interested in why this happens, more than I'm interested in the solution.
MainActivity.java
package it.damix.examples.servicesscce;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity extends Activity {
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
Log.d("ServiceSSCCE.MainActivity", "Service disconnected.");
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("ServiceSSCCE.MainActivity", "Service connected.");
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindService(new Intent(this, MyService.class), mConnection, Context.BIND_AUTO_CREATE);
}
public void scheduleAlarm(View view) {
AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getBroadcast(this, 101, new Intent(this, MyReceiver.class), 0);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, pi);
}
}
MyReceiver.java
package it.damix.examples.servicesscce;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
IBinder binder = peekService(context, new Intent(context, MyService.class));
if (binder == null)
Log.d("ServiceSSCCE.MyReceiver", "I just received a null binder.");
else
Log.d("ServiceSSCCE.MyReceiver", "Awesome, let's get this **** done!");
}
}
MyService.java
package it.damix.examples.servicesscce;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Messenger;
import android.util.Log;
public class MyService extends Service {
static class MyHandler extends Handler {
}
#Override
public IBinder onBind(Intent arg0) {
Log.d("ServiceSSCCE.MyService", "I've been bound.");
return new Messenger(new MyHandler()).getBinder();
}
#Override
public boolean onUnbind(Intent intent) {
Log.d("ServiceSSCCE.MyService", "I've been unbound.");
return super.onUnbind(intent);
}
#Override
public void onRebind(Intent intent) {
Log.d("ServiceSSCCE.MyService", "I've been rebound.");
super.onRebind(intent);
}
}
ApplicationManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="it.damix.examples.servicesscce"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="18"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="it.damix.examples.servicesscce.MyReceiver" android:enabled="true"></receiver>
<service android:name="it.damix.examples.servicesscce.MyService" android:enabled="true"></service>
</application>
</manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="it.damix.examples.servicesscce.MainActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me to schedule an alarm..."
android:onClick="scheduleAlarm"/>
</RelativeLayout>
Links
Done that
This too
Yep
Ah-ah
Something else that doesn't help
+1 for damix911's very complete statement of the problem and steps for possible resolution. The posting of all the code allowed me to easily recreate the test app.
The short answer to the question of why case #4 fails lies in some undocumented details of peekService()'s behavior. In this post by Android framework engineer Dianne Hackborn, she explains that for peekService() to return an IBinder, some component must have previously bound to the service, causing the system to create an IBinder. That post is the only place I have found those additional conditions for obtaining an IBinder described.
Here, for cases #1 through #3, an instance of MainActivity exists and has bound to the service, creating an IBinder. When the receiver runs and calls peekService(), it obtains that IBinder. For case #4, swiping the app from the recent task list kills the entire app process: the activity and bound service. When the alarm subsequently fires, the app process is recreated for the receiver, but the activity is not launched, there is no request to bind to the service, and the service is not created, so peekService() returns null.
I was not able to reproduce damix911's solution. When I modified the service attributes to make it run as an isolatedProcess I got a security exception (KitKat device). I question how starting the service and making it a foreground service would change anything. Starting it and returning the default (super) mode does cause the service to become sticky, so that when the process is recreated after the swipe the service will be recreated. But there is still nothing binding to it, so there is no IBinder for peekService() to return.
In short
The solution involves three things:
Making the service a foreground service.
Starting it in the activity using startService and binding to it. Aparently it's not enough for peekService to having started a service; aparently someone (an activity or probably another service) must have bound to it. Why this is the case it's beyond comprehension (to me).
Adding android:isolatedService="true" in the service declaration.
In detail
MyReceiver.java is correct.
The service declared in MyService.java needs indeed to be foreground:
public class MyService extends Service {
...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = new Notification.Builder(this)
.setTicker("Bla bla...")
.setContentTitle("Title...")
.setContentText("Text...")
.build();
startForeground(1234, notification);
return super.onStartCommand(intent, flags, startId);
}
...
}
This change in the service caused, at least one time, my activity to raise a connection leak warning (although I was not able to reproduce the behavior). However, it was fixed by properly unbinding the connection; this means removing the service code from onCreate and adding appropriate onResume and onStop methods to MainActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
startService(new Intent(this, MyService.class));
bindService(new Intent(this, MyService.class), mConnection, 0);
super.onResume();
}
#Override
protected void onStop() {
unbindService(mConnection);
super.onStop();
}
We are almost done. At this point (1.), (2.) and (3.) still work, and (4.) still doesn't work. The patient, actually got worse: now BroadcastReceive.onReceive doesn't even get triggered.
The final touch that fixes everything is adding the attribute android:isolatedService="true" to the service declaration in ApplicationManifest.xml.
<service
android:name="it.damix.examples.servicesscce.MyService"
android:enabled="true"
android:isolatedProcess="true"></service>

How to make sure the Broadcast Receiver is disconnected

I wrote a simple Broadcast Receiver which catches incoming calls and starts activity with the caller's number:
package com.example.nrsearch;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class CallReceiver extends BroadcastReceiver {
public CallReceiver() {
}
public Context context;
#Override
public void onReceive(Context context, Intent intent) {
Log.i("CallReceiverBroadcast", "onReceive() is called. ");
this.context = context;
TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener psl = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.i("CallReceiverBroadcast", "onCallStateChanged() is called. ");
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.i("CallReceiverBroadcast", "Incoming call caught. Caller's number is " + incomingNumber + ".");
startNumberDisplayActivity(incomingNumber);
}
}
};
teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
}
public void startNumberDisplayActivity(String incomingNumber) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("incomingNumber", incomingNumber);
context.startActivity(i);
}
}
However, after the first incoming call I feel like my device's battery starts to drain pretty quickly. I'm afraid that some process still prevents my Broadcast Receiver from disconnecting (I mean my Broadcast Receiver may be running forever). So, is there something in my code that could cause such a behavior and does this line really stops the TelephonyManager from listening for call state changes: teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE); or should I do it some other way?
EDIT: I'm almost sure that this class causes battery drain, because now I'm testing battery life with my app uninstalled and it's much lower than previous when this app was installed and broadcast receiver was called. I can't swear that this class is the cause of the drain but the battery consumption difference is clearly visible with and without this app. Could somebody look at this code and say what could cause the battety drain? Thanks in advance!
in the method
#Override
public void onPause() {
super.onPause();
mActivity.unregisterReceiver(myReceiver);
}
You can put this other places, but that's a good one. DO your registration in onResume.
Also please read the broadcastreceiver docs, they don't work the way you seem to believe they do:
http://developer.android.com/reference/android/content/BroadcastReceiver.html
Basically the receiver lifecycle is:
Receiver Lifecycle
A BroadcastReceiver object is only valid for the duration of the call
to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active.
This has important repercussions to what you can do in an
onReceive(Context, Intent) implementation: anything that requires
asynchronous operation is not available, because you will need to
return from the function to handle the asynchronous operation, but at
that point the BroadcastReceiver is no longer active and thus the
system is free to kill its process before the asynchronous operation
completes.
In particular, you may not show a dialog or bind to a service from
within a BroadcastReceiver. For the former, you should instead use the
NotificationManager API. For the latter, you can use
Context.startService() to send a command to the service.
Edit:
As per your comments - the concern about the BroadcastReceiver eating battery life isn't real. The receiver only lasts as long as it takes to run the code in it's on receiver method. At that point Android will clean it up as it deems nescesary. If anything in your code is breaking this it would be:
this.context = context;
/// these three lines
TelephonyManager teleMgr = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
.....
teleMgr.listen(psl, PhoneStateListener.LISTEN_CALL_STATE);
teleMgr.listen(psl, PhoneStateListener.LISTEN_NONE);
since you create a object and then try to listen on it.
However you should really read the docs:
anything that requires
asynchronous operation is not available,
Which is EXACTLY what you are doing in your code - attaching to a service and and waiting for its asyncronous response. This isn't acceptable in a BroadcastReceiver, and is clearly indicated in the docs at this point:
In particular, you may not show a dialog or bind to a service from
within a BroadcastReceiver.

Android starts my Service before the Air native extension calls it

I'm developing an Air (Flex) Mobile application for Android, which uses Air Native Extension (ANE) to take advantage of some platform functions that otherwise could not be used (at least to my knowledge). One of the platform functions that I want to use are services, specifically services that run as Foreground processes (using the startForeground() method).
When I invoke the service from my ANE everything works like a charm, the service is started correctly and it does what it needs to do but the problem is that Android seems to be trying to start it independently from my code, which, of course, results in errors that appear in the LogCat.
When I launch the application in debug mode in Flash Builder, and I use it for a while checking that the service works perfectly and no errors are thrown, after I close it from the Flash Builder (not from Eclipse ADT, which I also could) a couple of seconds later, the following errors appear:
01-16 10:56:06.953: E/AndroidRuntime(9757): java.lang.RuntimeException: Unable to start service com.mycompany.myextension.services.MyService#41594a50 with Intent { cmp=air.QOE.debug/com.mycompany.myextension.services.MyService }: java.lang.NullPointerException
01-16 10:56:06.953: E/AndroidRuntime(9757): at com.mycompany.myextension.services.MyService.onStartCommand(MyService.java:37)
It seems to be clear that Android tries to start the service but since its design to work inside the ANE -the extension is initialized but its context was already disposed- it crashes because it cannot reach the variables that are initialized within the context, therefore, ending in a crash or error the first time the code uses a context variable (line 37).
I would think that this has to do with the way I declared the service in my Android Manifest file. Next is part of the XML:
<application android:debuggable="true">
<service android:enabled="true" android:exported="true" android:name="com.mycompany.myextension.services.MyService">
<intent-filter>
<action android:name="air.com.mycompany.myextension.DO_CUSTOM_ACTION"/>
</intent-filter>
</service>
</application>
I hope you can tell me if I’m declaring the service incorrectly or if I’m making a mistake elsewhere. I appreciate the help.
EDIT: Service code
package com.mydomain.myapplicationextension.services;
import java.util.Timer;
import com.adobe.fre.FREContext;
import com.mydomain.myapplicationextension.myapplicationextension;
import com.mydomain.myapplicationextension.components.HttpServiceTask;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
public class MyApplicationService extends Service {
private Timer timer;
#Override
public IBinder onBind(Intent arg0) {
// Log.d("MyApplicationService", "onBind()");
return null;
}
#Override
public void onCreate() {
// Log.d("MyApplicationService", "onCreate()");
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Log.d("MyApplicationService", "onStartCommand(): " + myapplicationextension.applicationID);
Context appContext = myapplicationextension.applicationContext;
Intent launchIntent = appContext.getPackageManager().getLaunchIntentForPackage(myapplicationextension.appPackageName);
PendingIntent pendingLaunchIntent = PendingIntent.getActivity(appContext, 0, launchIntent, 0);
FREContext extContext = myapplicationextension.extensionContext;
int icon = extContext.getResourceId("drawable.notification_icon");
Notification notification = new Notification.Builder(appContext)
.setContentTitle(myapplicationextension.applicationID)
.setContentText(myapplicationextension.notificationMessage)
.setSmallIcon(icon)
.setContentIntent(pendingLaunchIntent)
.build();
startForeground(1,notification);
// Log.d("MyApplicationService", "startForegroundService()");
if(myapplicationextension.checkStatus)
{
timer = new Timer("Printer");
HttpServiceTask serviceTask = new HttpServiceTask(timer, launchIntent,myapplicationextension.statusServiceURL, myapplicationextension.triggerResponse);
timer.schedule(serviceTask, 0, 2000);
// Log.d("MyApplicationService", "startTimer()");
}
return START_STICKY;
}
#Override
public void onDestroy() {
// Log.d("MyApplicationService", "onDestroy():");
if(myapplicationextension.checkStatus)
{
timer.cancel();
timer = null;
// Log.d("MyApplicationService", "onDestroy(): timer.cancel():");
}
super.onDestroy();
}
}
When the phone runs out of memory and kills the service before it finishes executing. START_STICKY tells the OS to recreate the service after it has enough memory and call onStartCommand() again with a null intent. START_NOT_STICKY tells the OS to not bother recreating the service again. There is also a third code START_REDELIVER_INTENT that tells the OS to recreate the service AND redelivery the same intent to onStartCommand().
START_STICKY and START_NOT_STICKY
I have an ANE using START_STICKY that keeps launching the service

Scheduling a database update and shows a dialog

Ok, I think this is a recurring question, sorry for that. I need to update my DB collecting some data from web and display a dialog while the data are being downloaded.
I have my dialog, data comes fine and writes in database.
I'm doing some improvements. Today this works starting from one Activity. My will is this occurs in all application and start after a interval. And this is the moment when problems arise.
I'm using AlertManager to schedule my action. I have a BroadcastReceiver that, checks my database and starts to get data from web. At this point I'm facing problems. My progress dialog aren't shown and data doesn't come totally from web.
Code from BroadcastReceiver:
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
public class SchedulerUpdate extends BroadcastReceiver {
private Handler mHandler = null;
#Override
public void onReceive(Context context, Intent intent) {
try {
mHandler = new Handler();
Log.i("INFO", "SCHEDULED");
if(checkDataBase(context)){
updateData(context);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
private boolean checkDataBase(Context context){
String path = "/data/data/"+context.getPackageName()+"/databases/mdsdacpdatabase.db";
SQLiteDatabase database = null;
boolean result = false;
try{
database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.CREATE_IF_NECESSARY);
database.close();
result = true;
}
catch(SQLiteException e){
}
return result;
}
private void updateData(final Context context) {
((Activity)context.getApplicationContext()).showDialog(ID_DIALOG_PROGRESS_DOWNLOAD);
Runnable runnable = new Runnable(){
public void run(){
Log.i("INFO", "RUNNING");
...
mHandler.post(new Runnable() {
public void run() {
((Activity)context).dismissDialog(ID_DIALOG_PROGRESS_DOWNLOAD);
Log.i("INFO", "DONE");
}
});
};
};
new Thread(runnable).start();
}
}
Reading these posts on StackOverflow and on Kam:
BroadCast receiver dialog issue in Android
AlertDialog in BroadcastReceiver
show an alert dialog in broadcast receiver after a system reboot
How to send data from BroadcastReceiver to an Activity in android?
Android: Prefer Alarms and Intent Receivers to Services <--This is Kam
My conclusions are:
BroadcastReceivers can't display dialogs because they aren't
Activities(like Commonsware point out);
BroadcastReceivers can't
handle orientation issues that crashes app(I fix this in my activity
overriding onCreateDialog method);
Handlers aren't indicated to use
in BroadcastReceivers;
Services aren't indicated to do this kind of
task;
I thought a way to solve this. Creating a class that inherits from activity and inside that I handle orientation issues, schedule my broadcast in it to download the content at some time and displays dialog. And all of other classes inherits from it.
This solution works I think, but it's big workaround to solve the problem.
Sorry if my question is too long. I would like to discuss some other solutions(if what I proposed is a valid solution, I didn't tested).
A BroadcastReceiver object is only valid for the duration of the call
to onReceive(Context, Intent). Once your code returns from this
function, the system considers the object to be finished and no longer
active.
This has important repercussions to what you can do in an
onReceive(Context, Intent) implementation: anything that requires
asynchronous operation is not available, because you will need to
return from the function to handle the asynchronous operation, but at
that point the BroadcastReceiver is no longer active and thus the
system is free to kill its process before the asynchronous operation
completes.
In particular, you may not show a dialog or bind to a service from
within a BroadcastReceiver. For the former, you should instead use the
NotificationManager API. For the latter, you can use
Context.startService() to send a command to the service.
Source: http://developer.android.com/reference/android/content/BroadcastReceiver.html

Android broadcast reciever returns null pointer exception with extended application

Ive created a simple broadcast receiver whose only purpose is when the phone boots up to start an alarmmanager method that I tucked away in an extended application file that handles application wide tasks like this, this works fine when I call it from an activity but, when I try to call it from a broadcast receiver it crashes and does not work, what Im thinking is perhaps I need to append the context to it in some way?
here is my code :
package com.testapp21.second.activities;
import com.testapp21.second.OTweetApplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class PhoneOnReceiver extends BroadcastReceiver {
private OTweetApplication app;
#Override
public void onReceive(Context context, Intent intent) {
app.startChecks();
}
}
edit: startChecks then delegates off to a method in a helper file called startCheckshelper() here is what that block of code looks like this:
public void startCheckshelper(){
mAlarmSender = PendingIntent.getService(context,
0, new Intent(context, CheckerService.class), 0);
// We want the alarm to go off 30 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
// Schedule the alarm!
AlarmManager am = (AlarmManager)context.getSystemService(Service.ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, 60*1000, mAlarmSender);
}
You should always post your stack trace along with your question when asking about a crash in Android, but it looks like app is never initialized, yet you use it in onReceive.
You never initialized / assigned something to app, so it's null:
private OTweetApplication app;
And when you call it (app.startChecks();) you get the exception.

Categories

Resources