I am getting a
NullPointerException at android.app.ActivityThread$PackageInfo$ServiceDispatcher.doConnected(ActivityThread.java:1012)
My application is not even in the stack trace, so I have no idea what is going on.
I am trying to connect to a service when it happens.
How can I fix this problem?
This probably way too old for my response to be of any use, but in case anybody else has this problem, here's what it was for me. I am using a newer version of the SDK, so I'm getting this issue at line 1061.
It was happening to me because I was passing a null ServiceConnection object to the function bindService.
It was helpful to browse the SDK code in my case - although the line numbers don't add up due to version differences, the general code is likely the same (and I knew which method to check):
1097 // If there was an old service, it is not disconnected.
1098 if (old != null) {
1099 mConnection.onServiceDisconnected(name);
1100 }
1101 // If there is a new service, it is now connected.
1102 if (service != null) {
1103 mConnection.onServiceConnected(name, service);
1104 }
mConnection was pretty much the only thing that made sense to be null.
Related
While profiling my Google Cardboard application, I found out a very large memory leak (15Mb!) each time I left the activity with the 3D graphics.
After a long and grievous investigation, I found out that the source of the problem was a Context leak that happened each time I closed my CardboardActivity subclass.
The solution can be found in the accepted answer*
* wow... this is awkward... Note for any kind (and experienced) reviewer: I am writing a question to whom I know the answer already: am I supposed to do something for style, like add some fake suspense ("will our heroes prevail?! Find out in the accepted answer!"), like in a old Batman TV series or something?
After dicing and slicing my CardboardActivity subclass, until nothing else but the base class remained, I had to conclude that the base class itself was leaking the context.
I searched the web and found this post explaining how the activity in question leaked the context by failing to un-register a listener with a private instance of a class.
Upon trying to invoke said method manually (using reflection), I found out that in the current version of the Cardboard SDK (0.5.4 at the time of writing), the field is not present anymore.
Long story short: all sensors are now handled by an undocumented (yet public) SensorConnection class instantiated in CardboardActivity as a sensorConnection field, which is still plagued by the bug detailed in my first link.
This led me to this solution:
get the sensorConnection field in the CardboardActivity by reflection
use it to get the magneticSensor field, again by reflection
invoke the setOnCardboardTheaterListener with null argument, to clear the binding holding the reference to the Context in the Activity onDestroy method.
this boils down to the following code:
private void workAroundLeak() {
try {
// Get the sensor Connection
Class<?> c1 = Class.forName("com.google.vrtoolkit.cardboard.CardboardActivity");
Field sensorsField = c1.getDeclaredField("sensorConnection");
sensorsField.setAccessible(true);
SensorConnection sc = (SensorConnection) sensorsField.get(this);
if(sc == null) return;
// Get the magnetSensor
Class<?> c2 = Class.forName("com.google.vrtoolkit.cardboard.sensors.SensorConnection");
Field magnetField = c2.getDeclaredField("magnetSensor");
magnetField.setAccessible(true);
MagnetSensor ms = (MagnetSensor) magnetField.get(sc);
if(ms == null) return;
ms.setOnCardboardTriggerListener(null);
} catch(Exception e) {}
}
#Override
protected void onDestroy() {
workAroundLeak();
super.onDestroy();
}
which solved the problem entirely.
A word to the wise: since this solution relies on reflection, it might break (without consequences other than doing nothing, likely) as soon as Google will update the SDK (possibly fixing the issue in a clean way).
Hope this helps someone
I am using Android's MediaRouter / Presentation API (the support.v7 version).
Everything works fine so far. The only thing that doesn't is:
When I quit my activity (e.g.teardown & remove the callbacks), everything still works fine.
However, when starting this activity (the previous mediarouter-activity was forcefully finished, thus onPause/onDestroy was called FOR SURE => so those callbacks in there are gone too, as also shown in my debug messages) again at some later point in time, the callbacks get created and added and everything. Just, that there is no more onRouteAdded called, only onProviderChanged (With the default provider and thus useless).
It does always work like that (with wifi display [miracast], emulated secondary display, chromecast secondary display..). Are there any resolutions which are not in the examples?
Would you like to look at some code? Which special cases? (Can't post it all..)
I couldn't find anything so far, thanks for your help, in advance.
If you change the Google Cast sample app to support MediaRouter.Callback:
https://github.com/googlecast/CastPresentation-android
Then I'm getting the onRouteAdded called every time.
Using getSelectedRoute()instead of the RouteInfo (which is provided by the callbacks) did the job for me.
MediaRouter.RouteInfo selectedRoute = getHelper().getMediaRouter().getSelectedRoute();
if(provider != null && getCurrentRoute() != null && getCurrentRoute().equals(selectedRoute)){
Log.d(TAG, "only provider changes, dont do anything");
return false;
}
if (selectedRoute != null) {
setCurrentRoute(selectedRoute);
}
return updateContents();
this is definetly weird (as the rest of the code looks exactly as in the provided google android developer samples), but it works.
I know this problem was resolved over 1 year ago, but probably it isn't the perfect solution. Maybe it will be useful for somebody else.
I had similar problem with exactly the same symptoms (no more onRouteAdded called). In my situation it was caused by improperly implemented deactivation of MediaRouter: to deactivate it properly you should not only remove all of callbacks, but select default MediaRoute as well.
if (!mMediaRouter.getDefaultRoute().isSelected()) {
mMediaRouter.getDefaultRoute().select();
}
I've had in app billing v3 implemented in my app for about a week now. I used a lot of android's sample code to simplify the integration. I've been logging a crash fairly often that I can't seem to reproduce:
Exception Type: java.lang.RuntimeException
Reason: Unable to destroy activity {[package].billing.BillingActivity}: java.lang.IllegalArgumentException: Service not registered: [package].billing.util.IabHelper$1#40646a70
It seems to be breaking on this line:
if (mContext != null) mContext.unbindService(mServiceConn);
I'm binding this service in my onCreate method and disposing it in my onDestroy method (which is where this error is logged). Any pointers?
You could replace the line you mentioned:
if (mContext != null) mContext.unbindService(mServiceConn);
by this line
if (mContext != null && mService != null) mContext.unbindService(mServiceConn);
This should do the trick
I checked out the latest version of the sample project and up to today my recommendation is to currently to NOT use IabHelper. It is massively flawed.
To give you an idea:
1.) the async methods of IabHelper start a new thread. If IabHelper.dispose() is called while a thread is running you will always get various exceptions you cannot even handle.
2.) If the connection to the billing service goes down, they set it to null. But apart from that they never check if mService is null before accessing the methods. So it will always crash with NullPointerException in this case.
public void onServiceDisconnected(ComponentName name) {
logDebug("Billing service disconnected.");
mService = null;
and this is just the tip of the ice berg. Seriously I do not understand how somebody can publish this as reference code.
I just encountered the same issue but on android emulator. Billing v3 requires that Google Play app should be launched at least once and since the emulator lack of Google Play app it cannot set up helper and cannot dispose it in onDestroy().
My personal workaround is just skipping that error in try/catch:
#Override
protected void onDestroy() {
super.onDestroy();
if (bHelper != null){
try {
bHelper.dispose();
}catch (IllegalArgumentException ex){
ex.printStackTrace();
}finally{}
}
bHelper = null;
}
Add this in every onDestroy() where you dispose helper. Works fine for me.
The IabHelper class is working in a normal way.
What you need to do is:
when you call startSetup for the helper, you need to pass a callback IabHelper.OnIabSetupFinishedListener which will tell you the result of starting setup. If you get failure in the callback, the service connection with the google play services was not established.
You should handle future calls to IabHelper depending upon the result received in IabHelper.OnIabSetupFinishedListener. You can surely keep a boolean field to know what was the status.
The answer sam provided is actually a trick (in his own words). The helper classes aren't supposed to throw exceptions so that the user of those classes can implement some task in such scenarios.
And of-course, try/catch is best way if you don't want to go in details (whenever anything breaks due to exception, surely first thing which comes in mind is to put that in a try/catch block).
My activity's onInit() contains a call to TextToSpeech.setEngineByPackageName():
tts = new TextToSpeech(this, this);
tts.setEngineByPackageName("com.ivona.tts.voicebeta.eng.usa.kendra");
It works on an Android 2.2.2 device, but on an Android 2.3.4 device it produced a NullPointerException, with the following stack trace:
E/TextToSpeech.java - setEngineByPackageName(3423): NullPointerException
W/System.err(3423): java.lang.NullPointerException
W/System.err(3423): at android.os.Parcel.readException(Parcel.java:1328)
W/System.err(3423): at android.os.Parcel.readException(Parcel.java:1276)
W/System.err(3423): at android.speech.tts.ITts$Stub$Proxy.setEngineByPackageName(ITts.java:654)
W/System.err(3423): at android.speech.tts.TextToSpeech.setEngineByPackageName(TextToSpeech.java:1356)
Since I am providing a hard-coded string parameter, I know that the parameter isn't what's causing the NullPointerException.
I also know that setEngineByPackageName() is deprecated but that's only since API 14, so this couldn't be the reason.
Any idea what could be causing this NullPointerException?
EDIT: I wouldn't have been concerned with the "why" if this didn't result in an endless bombardment of:
I/TextToSpeech.java(3652): initTts() successfully bound to service
Followed by calls to onInit() (by the system, not by my code).
My hope is that if I underderstand why this is happening, I can stop the bombardment of onInit()s and recover gracefully from the error.
Is the TTS engine you are referencing installed on the 2.3.4 device? If it is, it might be a platform bug.
EDIT:
Don't remember what results I got when I did this, but calling setEngineByPackageName() when the package doesn't exists is not a good idea. Check if it is installed and don't try to use it if it's not. Something like:
boolean isPackageInstalled(String packageName) {
PackageManager pm = context.getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(packageName, 0);
return pi != null;
} catch (NameNotFoundException e) {
return false;
}
}
Attempting to investigate this myself, in case an expert on the subject isn't around:
The NullPointerException stack trace is printed by setEngineByPackageName() itself in the catch handler for this try clause:
try {
result = mITts.setEngineByPackageName(enginePackageName);
if (result == TextToSpeech.SUCCESS){
mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName;
}
}
Which suggests that either of the following is null:
mITts
mCachedParams
mCachedParams is unlikely to be the null one because it is initialized in the constructor. So this leaves us with mITts:
If I examine TextToSpeech.initTts() I can easily spot 2 points in which mITts can remain null:
onServiceConnected()
onServiceDisconnected()
But why this is happening only on the 2.3.4 device? This is still a mystery.
Possible clue: The method TextToSpeech.initTts() ends with the following comment:
mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
// TODO handle case where the binding works (should always work) but
// the plugin fails
Which may explain why I receive a barrage of onInit()s ("initTts() successfully bound to service"): Binding always works, but since the package is not installed, "the plugin fails".
The question now is how to stop this endless loop...
How to abort/interrupt a LocalServerSocket waiting, in a background thread, for a connection in method LocalServerSocker.accept() ?
I've tried to call close() method from another thread, but it does not seem to work.
There is a ticket opened for it in Android project: http://code.google.com/p/android/issues/detail?id=29939.
Seems the problem is confirmed by Google, as the first comment is:
i think we should rewrite this to use the same underlying libcore
stuff, and get the interruption behavior for free.
The workaround can be to send a custom shutdown command to the LocalServerSocket from another thread to unblock accept.
Instead of localSocket.close, use this: (requires API 21+)
try {
Os.shutdown(localSocket.fileDescriptor, OsConstants.SHUT_RDWR)
} catch (e: ErrnoException) {
if (e.errno != OsConstants.EBADF) throw e // suppress fd already closed
}