Android Wear Watchface and the WakeLock - android

I'm developing a watchface for Android Wear using the WatchFace API (extending CanvasWatchFaceService).
I've used the code from here to build a ticker that run code every second.
I'm experiencing the following problem. Every now and then the service crashes with this exception. I can't understand where it comes from, if you have any lead I'll post additional code.
01-06 11:22:00.247 12965-12965/com.my.package E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.my.package, PID: 12965
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.PowerManager$WakeLock.acquire()' on a null object reference
at android.support.wearable.watchface.WatchFaceService$Engine.onCommand(WatchFaceService.java:201)
at android.service.wallpaper.WallpaperService$Engine.doCommand(WallpaperService.java:977)
at android.service.wallpaper.WallpaperService$IWallpaperEngineWrapper.executeMessage(WallpaperService.java:1191)
at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCaller.java:37)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
After this crash the watchface stops working and to make it start again I have to choose another watchface, then reselect mine, so it's a total show stopper!

Props to David for the lead on super. calls - it turns out that was the problem. Specifically, the CanvasWatchFaceService.Engine.onCreate method needs to call through to its ancestor, as such:
private class Engine extends CanvasWatchFaceService.Engine {
#Override
public void onCreate(SurfaceHolder holder) {
super.onCreate(holder);
// your engine initialization code here
}
// other watch face engine code
}
Without the super.onCreate(holder); call, my watch face would crash within minutes; with it, it happily ran overnight.
As an aside, this is something missing from the Android developer documentation; specifically, the Training page for Building a Watch Face Service doesn't include this ancestor call in its code sample.

The code you linked lacks some important parts, that are dotted. I.e. have you defined the update rate?
private static final long INTERACTIVE_UPDATE_RATE_MS = TimeUnit.SECONDS.toMillis(1);
Fully implemented it works well. See AnalogWatchFaceService in code samples: Wearable/Watchface face.

Related

OnePlus Nord devices with Android 10 are painful! đŸ˜”

We have an enterprise application being developed, and since the project inception, we're facing a constant crash only in OnePlus Nord devices.
We tried to reproduce in our devices, and it's not getting reproduced, but Firebase Crashlytics always reports it in live application. Description as:
cpe.java line 11
com.oneplus.theme.cpe.onViewAttachedToWindow
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.removeOnAttachStateChangeListener(android.view.View$OnAttachStateChangeListener)' on a null object reference
at com.oneplus.theme.cpe.onViewAttachedToWindow(cpe.java:11)
at android.view.View.dispatchAttachedToWindow(View.java:20272)
at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3455)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2273)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1960)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8228)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
at android.view.Choreographer.doCallbacks(Choreographer.java:1041)
at android.view.Choreographer.doFrame(Choreographer.java:953)
at android.view.Choreographer$FrameHandler.handleMessage(Choreographer.java:1163)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7711)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
At this stage, as it is working fine on all other devices, we couldn't pinpoint any code which could be causing this issue.
Being reported with many OnePlus Nord users, this issue brings our crash free % down significantly! How to fix this?
It's some view related problem I think.
It's saying that you're using listener on null view object. So check if you are getting the view first & then applying listener.
You can use GlobalLayoutListener to check if the view has finished Drawing.
yourView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
yourView.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
//Your logic here (You can Put the OnAttachStateChangeListener here)
}
});

Strange NPE deep inside MediaSessionCompat

I have seen similar questions posted about MediaSessionCompat but they are all pretty old, in fact most predate AndroidX and they point at it being fixed in newer versions.
This crash is happening with androidx.media:media:1.2.1 on various phones from Android 8 through 11. It is always MediaSessionImplApi21. Works fine for me on every phone I've tried.
This issue is new for me as of my latest release. The two big changes I made are that I added a progress bar to my MediaStyle notification and that I upgraded to 1.2.1 from 1.0.0.
This is the exception:
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.media.session.MediaSessionCompat$Callback android.support.v4.media.session.MediaSessionCompat$MediaSessionImplApi21.getCallback()' on a null object reference
at android.support.v4.media.session.MediaSessionCompat$Callback$MediaSessionCallbackApi21.getSessionImplIfCallbackIsSet(MediaSessionCompat.java:1907)
at android.support.v4.media.session.MediaSessionCompat$Callback$MediaSessionCallbackApi21.onMediaButtonEvent(MediaSessionCompat.java:1597)
at android.media.session.MediaSession$CallbackMessageHandler.handleMessage(MediaSession.java:1471)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7094)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)
If my Callback wasn't set them a lot of things wouldn't work.
Also my code looks like this:
MediaSessionCompat mediaSessionCompat = new MediaSessionCompat(context, TAG);
mediaSessionCompat.setCallback(mediaSessionCallback);
So there's really no room to not set the Callback.
Any idea what it could be?
From looking at the code and where it crashed:
private MediaSessionImplApi21 getSessionImplIfCallbackIsSet() {
MediaSessionImplApi21 sessionImpl;
synchronized (mLock) {
sessionImpl = (MediaSessionImplApi21) mSessionImpl.get();
}
return MediaSessionCompat.Callback.this == sessionImpl.getCallback()
? sessionImpl : null;
}
It is crashing on sessionImpl.getCallback(). Which probably means it either got recycled because mSessionImpl is a WeakReference or it was set to null to begin with.
Turns out it was a bug and has now been patched and will hopefully be out on 1.2.2 https://issuetracker.google.com/issues/178694750

Sporadic IllegalArgumentException: Unknown URL content://

Very rarely getting:
Fatal Exception: java.lang.IllegalArgumentException: Unknown URL content://com.example.provider/info
at android.content.ContentResolver.insert(ContentResolver.java:1252)
Fatal Exception: java.lang.IllegalArgumentException: Unknown authority com.example.provider
at android.content.ContentResolver.applyBatch(ContentResolver.java:1247)
Emphasis on rarely. Generally work fine without issue, so the authorities is set up fine, but this is showing up every once in a while for no reason. Are there reasons why the ContentResolver may not be able to find a ContentProvider (i.e. if not set up yet)?
I've had the rare IllegalArgumentException with Unknown URIs issue when I was doing ContentResolver operations in the custom Application object.
For example, I was trying to delete items in my content provider in the application onCreate method which would very occasionally crash:
public class CustomApplication extends Application {
#Override
public void onCreate() {
//..
context.getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
//..
}
}
Which would sometimes render the following crash:
Fatal Exception: java.lang.RuntimeException: Unable to create application com.myapp.CustomApplication: java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6431)
at android.app.ActivityThread.access$1800(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7331)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by java.lang.IllegalArgumentException: Unknown URL content://com.myapp.db.CustomContentProvider/reminder
at android.content.ContentResolver.delete(ContentResolver.java:1376)
at com.myapp.ReminderEntryDao.delete(Unknown Source)
at com.myapp.CustomApplication.onCreate(Unknown Source)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1037)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6428)
at android.app.ActivityThread.access$1800(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1887)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7331)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
I also saw similar behaviour with a BOOT_COMPLETE receiver. I had about 70 reported crashes with this exception (mostly Infinix devices ~43%, hardly any Samsung Devices) of about 200 000 monthly active users.
I moved this into a background scheduled job and haven't seen the crash since. I was only ever able to reproduce this issue once on a Nexus device that I used but never again.
I suspect perhaps sometimes on some versions of Android on some devices the Application/BOOT_COMPLETE Receiver initializes before the ContentProvider is fully initialized and therefore when it tries to access it, it is not properly set up yet.
There are a couple of stackoverflow posts that do state exactly what is created first and how the OS should behave:
Is the Application class guaranteed to be instantiated before a defined boot receiver is called
But like I said, I've seen otherwise and moving operations out of the classes into background schedulers seems to fix the problem (perhaps it is just because it takes a bit longer to get setup). Hopefully my experience will help you.
Edit: I used the evernote job dispatcher and deferred my ContentResolver operations to the job if required. (but I would assume that deferring the content provider operation to any kind of background processing might fix it as it had a bit more time to get setup - these are just my suspicions of course).
class DeleteRemindersJob extends Job {
#NonNull
#Override
protected Result onRunJob(final Params params) {
cursor = getContext().getContentResolver().delete(ReminderEntry.getContentURI(), null, null, null, null);
//..
return Result.SUCCESS;
}
}

Jasypt fails to initialize on Android 5.1.1 and above, ClassLoader is null

I was using Jasypt (compile 'org.jasypt:jasypt:1.9.2') normally with a Standard PBE encryptor
StandardPBEByteEncryptor strongBinaryEncryptor = new StandardPBEByteEncryptor();
strongBinaryEncryptor.setAlgorithm("...");
strongBinaryEncryptor.setKeyObtentionIterations(...);
strongBinaryEncryptor.setProviderName(BouncyCastleProvider.PROVIDER_NAME);
strongBinaryEncryptor.setPassword("...");
byte[] encryptedBytes = strongBinaryEncryptor.encrypt(bytes);
And this used to work without a problem, but now it crashes with the following root exception:
E/AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String)' on a null object reference
E/AndroidRuntime: at org.jasypt.normalization.Normalizer.initializeIcu4j(Normalizer.java:139)
E/AndroidRuntime: at org.jasypt.normalization.Normalizer.normalizeToNfc(Normalizer.java:96)
E/AndroidRuntime: at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.initialize(StandardPBEByteEncryptor.java:661)
E/AndroidRuntime: at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.encrypt(StandardPBEByteEncryptor.java:873) 
The same code works on Kitkat phone and the Lollipop emulator, but for example crashes on a OnePlusOne.
If you look at the source, what you see is this:
static void initializeIcu4j() throws ClassNotFoundException {
Thread.currentThread().getContextClassLoader().loadClass(ICU_NORMALIZER_CLASS_NAME);
useIcuNormalizer = Boolean.TRUE;
}
Which means Thread.currentThread().getContextClassLoader() is null. This didn't use to happen, and I don't really know what caused this change in behavior. I also am not sure what I should do to fix it.
Any ideas?
Based on a wiki page that has since been removed from Google Code, this actually used to be a bug in Dalvik as well, but a patch was commited in Froyo. However, ART seems to have resurfaced this exact same problem.
Apparently as per https://web.archive.org/web/20120303234738/http://code.google.com/p/dalvik/wiki/JavaxPackages the solution is to initialize the class loader manually in Activity.onCreate().
public class HelloStax extends Activity {
#Override public void onCreate(Bundle savedInstanceState) {
...
/*
* Ensure the factory implementation is loaded from the application
* classpath (which contains the implementation classes), rather than the
* system classpath (which doesn't).
*/
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
...
}

Exception in the Android's code while starting the app

In the "Crashes and ANRs" of the Google Play Developer console I've got such a report:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.AssetManager android.content.res.Resources.getAssets()' on a null object reference
at android.app.LoadedApk.getAssets(LoadedApk.java:590)
at android.app.LoadedApk.makeApplication(LoadedApk.java:646)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5088)
at android.app.ActivityThread.access$1600(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1509)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5944)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1389)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1184)
The device that has this problem is Galaxy S4 and runs Android 5.0
What it can be - there is not a single line from my code, why does it fail?
Thanks a lot!
I've got this in my console too.
It seems this occurs when users start the app when it's currently being updated or just after that.
A possible workaround would be to check if getResources returns null when the application start, and kill it if it does:
public class DevToolsApplication extends Application {
private static final String TAG = "DevToolsApplication";
#Override
public void onCreate() {
super.onCreate();
AppLogger.i(TAG, "app start...");
checkAppReplacingState();
}
private void checkAppReplacingState() {
if (getResources() == null) {
AppLogger.w(TAG, "app is replacing...kill");
Process.killProcess(Process.myPid());
}
}
}
See this for more information
https://issuetracker.google.com/issues/36972466
Make sure that anywhere you call getAssets(), you call it as:
getApplicationContext().getAssets()
It would appear as if you are calling getAssets() in a class that does not have the application context available, hence the fact that it is null.
I've got the same exception while added the below overlay in the AndroidManifest.xml file. Even after removing the Overlay code, landed into the above exception.
<overlay android:targetPackage="com.android.systemui"
android:priority="1"/>
Just close the Android Studio completely. Open the project again. Clean and Build the exception got cleared.

Categories

Resources