I have an app with :
an activity class that allows the user to set multiple alarms.
a service class to manage those alarms in the background.
a receiver class to do certain work when the alarm is called.
Everything works fine.
Now I want to automatically start the service when the phone boots up. The onBootReceiver is received but the app crashes (NPE) when this line is reached in my service class:
Intent intent = new Intent (MainActivity.getContext(),AReceiver.class);
I can't use this instead of MainActivity.getContext() either.
Any ideas of what may be causing this?
Thanks :)
From your code sample, it looks like the MainActivity class is not being initialized when being passed into the Intent. This means that the getContext() method will return a null value, and thats where your error is.
You need to use getContext() or getApplicationContext() from a initialized object. If this proves impossible, you could do something like this.
Related
My BroadcastReceiver receives Intent.ACTION_NEW_OUTGOING_CALL. It needs to call this.setResultData(null) so that the number is not subsequently dialled, as described here.
This works fine.
How can I test this with Robolectric?
This is what I have:
// Create the intent
Intent myIntent = new Intent("Intent.ACTION_NEW_OUTGOING_CALL");
myIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, "123");
// Find my BroadcastReceiver
List<BroadcastReceiver> receivers = ShadowApplication.getInstance().getReceiversForIntent(myIntent);
MyReceiver receiver = (MyReceiver)receivers.get(0);
// Invoke it - I understand this is the correct way to do it in a Robolectric test
Context context = ShadowApplication.geInstance().getApplicationContext();
receiver.onReceive(context, myIntent);
My Broadcast receiver is launched, but when it calls setResultData() an exception is raised: java.lang.IllegalStateException: Call while result is not pending. This happens due to the state of the underlying BroadcastReceiver because setResultData()->checkSynchronousHint() finds that mPendingResult==null.
mPendingResult is only ever set non-null by setPendingResult(), which I cannot call (even using reflection).
What is the proper way to test BroadcastReceiver which needs to call setResultData() please?
I've tried to reproduce your issue and was not able.
Take a look to my test https://github.com/emartynov/robolectic-experiments/blob/master/robolectric-3.0-test/src/test/java/com/bijdorpstudio/myapplication/IncomingCallReceiverTest.java
However, I was not able to get BroadcastReceiver to be picked up by Robolectric from AndroidManifest.xml. Added by hand in tests.
And I think it is OK approach. I would add some xml test for correct BroadcastReceiver tagging in AndroidManifest.xml. Testing that android is correctly picking it up will be still my lowest priority task
I have a BroadcastReceiver, and on its OnReceive I am supposed to call a method which is defined in the MainActivity. wherever I searched I found that I will have to write the following code.
Bundle bundle = intent.Extras;
Intent callingIntent = new Intent(context, typeof(MainActivity));
callingIntent.PutExtra("isSynched", true);
callingIntent.AddFlags(ActivityFlags.NewTask);
callingIntent.AddFlags(ActivityFlags.SingleTop);
context.StartActivity(callingIntent);
Now this calls my method, but the app keeps opening up. I don't want that to happen. I want the method to be called when the app is in background and want the app to be in background. What should I do? I am using xamarin to write the code.
I have created a service that gets the data but after I receive data I have to call a method in MainActivity to update the calendar. I am currently doing it in OnReceive like this, public override void
OnReceive(Context context, Android.Content.Intent intent)
{
if (context.GetType().Equals(typeof(MainActivity)))
{
((MainActivity)context).SyncCalendar();
}
}
this context is coming as restrictedaccess. So not able to call SyncCalendar Method
Depending on whether you need or not execute that code all the time your app lives, I'd recommend:
AsyncThread: This is somelike an improved version of a Thread as it already implements some of the mechanisms you would need to set manually with a Thread, but it's not recommended to execute all your app life, just for ending processes. You may find more info there
Service: Otherwise, if your function is intended to run all your app's life long, Service is the correct choice. It's a bit harder to understand than the AsyncThread, as it's a class that it's executed until you stop it paralelly to your main UI, but it's not a thread. You may find this useful and also this.
I have managed to get an Activity to start from my onReceive() methdod, but I really need to do a startActivityForResult();.
Is there any way I could do this?
On a side note, how would I make my app become a 'camera' app, as in it would appear when an app started the intent to take a picture?
The important thing to know about broadcast receivers is that you should not add long running processes in it, because after something like 5 seconds your app will crash.
The best thing to do in your case is to intent to other Activity from your broadcast receiver, and from that activity use startActivityForResult(), get the picture and continue from there...
startActivityForResult can only be called from an Activity since it is defined in the Activity class and require instance of activity.
You can only call startAcivity() from broadcast receiver since in onRecieve() you only have access to generic context object and it does not have startActivityForResult method defined in the class..
Im trying to make an scheduled activity go off every hour or so, all working in the background.
Right now i have a BroadcastReceiver that picks up when the device is booted.
The BroadcastReceiver creates a PendingIntent to an activity (Called AlarmController) that creates has all necessary methods that i need for making the scheduled activity to go off.
How ever, this doesnt seem to work.
This is how my BroadcastReciever class onReceive{} looks like and is indentical to my main activity onCreate{}(Only for testing)
Intent intent = new Intent(serviceactivirt.this, AlarmController.class);
PendingIntent sender = PendingIntent.getActivity(serviceactivirt.this, 0, intent, 0);
try {
sender.send();
} catch (CanceledException e) {
Toast.makeText(getApplicationContext(), "FEJLSAN", Toast.LENGTH_LONG).show();
}
This actually works, except that my app crashes at launch, but the scheduled activity is working...
Any ideas? Is this "The way to do it" or is there a more recommended way?
Cheers!
Solution:
Instead of having a BroadcastReciever calling an Activity, i made the BroadcastReciever starting a Service. And changed my Activity to a Service, programmaticly and in manifest.
Works great!
Im trying to make an scheduled activity go off every hour or so, all working in the background.
Please allow users to configure other options, such as using a Notification, rather than being interrupted by an activity taking over the foreground.
Right now i have a BroadcastReceiver that picks up when the device is booted.
You would only need that to set up an AlarmManager schedule for your hourly events. Your PendingIntent for the AlarmManager could be one you obtain via getActivity().
How ever, this doesnt seem to work.
If you want to start an activity, call startActivity(). Do not create a PendingIntent, then immediately send() the PendingIntent.
Also, get rid of getApplicationContext() and simply use this.
except that my app crashes at launch
Use adb logcat, DDMS, or the DDMS perspective in Eclipse to examine LogCat and look at the stack trace associated with your crash.
In this code snippet, what Activity class do I use? The one where the code is written? Is this statusbar message going somewhere?
Intent notificationIntent = new Intent(this, MyActivity.class);
Does this method act immediately or it's done later?
NotificationManager.notify();
In this code snippet, what Activity class do I use?
How should we know? We are not mind readers, and you have given us one line out of a much larger example somewhere.
Taking a completely random guess, that is probably the activity that should be opened when the user taps on the notification entry.
Does this method act immediately or it's done later?
The call is asynchronous, but it should be displayed almost immediately.