Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android 13 Crash #1083

Closed
DarrenMiddleton opened this issue Apr 19, 2022 · 13 comments
Closed

Android 13 Crash #1083

DarrenMiddleton opened this issue Apr 19, 2022 · 13 comments

Comments

@DarrenMiddleton
Copy link

When I start ranging for Bluetooth devices using the altbeacon library I get the following crash.

java.lang.RuntimeException: Unable to create service org.altbeacon.beacon.service.BeaconService: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference at android.app.ActivityThread.handleCreateService(ActivityThread.java:4524) at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2153) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7850) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference

It happens on all Android devices I have tested that are running Android 13. The altbeacon library version is 2.19.

@DarrenMiddleton DarrenMiddleton changed the title Library causes app to crash Android 13 Crash Apr 19, 2022
@joeywittig
Copy link

Same is happening for me.

@davidgyoung
Copy link
Member

After reviewing the documents changes in Android 13, I see nothing announced that might cause the problem. This appears to be a bug in Android 13.

In ActivityThread.java:4524 (inside handleCreateService) there is a call to xxxxx.toString() when xxxx is null, thereby causing a crash. Unfortunately Android 13 source is not available. If I look at the latest version of that ActivityThread.java the lines don't match up:

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/ActivityThread.java#4516

However, I do see a number of string concatenations that would cause a toString() call like this: Slog.v(TAG, "Creating service " + data.info.name);

Could data.info.name be unexpectedly null?

This should come from the android:name element of the XML declaration of the BeaconService, which is declared in the library AndroidManifest.xml file as:

        <service android:enabled="true"
            android:exported="false"
            android:isolatedProcess="false"
            android:label="beacon"
            android:name=".service.BeaconService"
            />

But maybe something in Android 13 causes this to become null later on?

You might try two things:

  1. Check your merged manifest after a build and see if this service declaration has a proper name like android:name="org.altbeacon.beacon.service.BeaconService". You should find that in build/intermediates/merged_manifests/debug/AndroidManifest.xml. If it does not have a name declaration this could be the problem, and the next option might help.

  2. You could try making your own service entry in your app's AndroidManifest.xml to override this declaration and force the service to have a name. You could do something like this:

    <service android:name="org.altbeacon.beacon.service.BeaconService"
                    android:exported="false"
                    android:isolatedProcess="false"
                    android:label="beacon"
                    android:name="org.altbeacon.beacon.service.BeaconService"
                     tools:node="replace">
    </service>

@FabienWitick
Copy link

I have the same issue. I checked the merged manifest and I do have android:name="org.altbeacon.beacon.service.BeaconService".

@davidgyoung
Copy link
Member

@FabienWitick can you please share your full merged manifest declaration in case that gives any clues?

@DarrenMiddleton , did you try the suggestion you posted? I wouldn't think the android:isolatedProcess="true" would be helpful -- I would think that would break the library's ability to send scan results via the library APIs.

@FabienWitick
Copy link

Here is my full merged manifest :
`

<uses-sdk
    android:minSdkVersion="21"
    android:targetSdkVersion="30" />

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission
    android:name="android.permission.BLUETOOTH"
    android:required="false" />
<uses-permission
    android:name="android.permission.BLUETOOTH_ADMIN"
    android:required="false" />
<uses-permission android:name="android.permission.VIBRATE" />

<uses-permission-sdk-23 android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission-sdk-23 android:name="android.permission.VIBRATE" />

<!-- Don't require camera, as this requires a rear camera. This allows it to work on the Nexus 7 -->
<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera.front"
    android:required="false" /> <!-- TODO replace above two with next line after Android 4.2 -->
<!-- <uses-feature android:name="android.hardware.camera.any"/> -->
<uses-feature
    android:name="android.hardware.camera.autofocus"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera.flash"
    android:required="false" />
<uses-feature
    android:name="android.hardware.screen.landscape"
    android:required="false" />
<uses-feature
    android:name="android.hardware.wifi"
    android:required="false" />

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Required by older versions of Google Play services to create IID tokens -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />

<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<application
    android:name="com.myzee.witick.AppSingleton"
    android:allowBackup="false"
    android:appComponentFactory="androidx.core.app.CoreComponentFactory"
    android:debuggable="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme" >
    <meta-data
        android:name="com.mixpanel.android.MPConfig.EventsEndpoint"
        android:value="https://api-eu.mixpanel.com/track" />
    <meta-data
        android:name="com.mixpanel.android.MPConfig.PeopleEndpoint"
        android:value="https://api-eu.mixpanel.com/engage" />
    <meta-data
        android:name="com.mixpanel.android.MPConfig.GroupsEndpoint"
        android:value="https://api-eu.mixpanel.com/groups" />
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@mipmap/ic_notif" />
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/colorPrimary" />

    <activity
        android:name="com.myzee.witick.features.account.paymentMethods.PaymentMethodsActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.landing.LandingActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.register.RegisterActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize|stateHidden" />
    <activity
        android:name="com.myzee.witick.features.authentication.AuthenticationActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize|stateHidden" />
    <activity
        android:name="com.myzee.witick.features.V3MainActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize|stateHidden" />
    <activity
        android:name="com.myzee.witick.launcher.LauncherActivity"
        android:screenOrientation="portrait"
        android:theme="@style/SplashTheme.LightStatusBar" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name="com.myzee.witick.features.bluetooth.EnableBluetoothActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.payment.scellius.ScelliusActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.location.LocationActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.MainActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.information.UserInfoActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.information.EditEmailActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize|stateHidden" />
    <activity
        android:name="com.myzee.witick.features.account.information.EditPasswordActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize|stateHidden" />
    <activity
        android:name="com.myzee.witick.features.account.history.HistoryActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.history.PurchaseHistoryActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.history.ValidationHistoryActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.help.HelpActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.about.AboutActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.help.HelpQuestionActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.common.WebActivity"
        android:screenOrientation="portrait" />
    <activity
        android:name="com.myzee.witick.features.account.code.CodeActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize|stateHidden" />
    <activity
        android:name="com.myzee.witick.features.payment.stripe.StripeActivity"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize|stateHidden" />

    <!-- [START firebase_service] -->
    <service
        android:name="com.myzee.witick.firebase.MessagingService"
        android:exported="false" >
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    <!-- [END firebase_service] -->

    <activity
        android:name="com.stripe.android.view.AddPaymentMethodActivity"
        android:theme="@style/StripeDefaultTheme" />
    <activity
        android:name="com.stripe.android.view.PaymentMethodsActivity"
        android:theme="@style/StripeDefaultTheme" />
    <activity
        android:name="com.stripe.android.view.PaymentFlowActivity"
        android:theme="@style/StripeDefaultTheme" />
    <activity
        android:name="com.stripe.android.view.PaymentAuthWebViewActivity"
        android:theme="@style/StripeDefaultTheme"
        android:windowSoftInputMode="adjustResize" />
    <activity
        android:name="com.stripe.android.view.PaymentRelayActivity"
        android:theme="@style/StripeDefaultTheme" />
    <activity
        android:name="com.stripe.android.view.Stripe3ds2CompletionActivity"
        android:theme="@style/StripeDefaultTheme" />
    <activity
        android:name="com.stripe.android.paymentsheet.PaymentSheetActivity"
        android:screenOrientation="portrait"
        android:theme="@style/StripePaymentSheetDefaultTheme" />
    <activity
        android:name="com.stripe.android.paymentsheet.PaymentOptionsActivity"
        android:screenOrientation="portrait"
        android:theme="@style/StripePaymentSheetDefaultTheme" />
    <activity
        android:name="com.stripe.android.googlepay.StripeGooglePayActivity"
        android:screenOrientation="portrait"
        android:theme="@style/StripeGooglePayDefaultTheme" />
    <activity
        android:name="com.stripe.android.stripe3ds2.views.ChallengeActivity"
        android:theme="@style/Stripe3DS2Theme" />
    <activity
        android:name="com.stripe.android.stripe3ds2.views.ChallengeProgressActivity"
        android:theme="@style/Stripe3DS2Theme" />
    <activity
        android:name="com.journeyapps.barcodescanner.CaptureActivity"
        android:clearTaskOnLaunch="true"
        android:screenOrientation="sensorLandscape"
        android:stateNotNeeded="true"
        android:theme="@style/zxing_CaptureTheme"
        android:windowSoftInputMode="stateAlwaysHidden" />

    <receiver
        android:name="org.altbeacon.beacon.startup.StartupBroadcastReceiver"
        android:exported="false" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
            <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
        </intent-filter>
    </receiver>

    <service
        android:name="org.altbeacon.beacon.service.BeaconService"
        android:enabled="true"
        android:exported="false"
        android:isolatedProcess="false"
        android:label="beacon" />
    <service
        android:name="org.altbeacon.beacon.BeaconIntentProcessor"
        android:enabled="true"
        android:exported="false" />
    <service
        android:name="org.altbeacon.beacon.service.ScanJob"
        android:exported="false"
        android:permission="android.permission.BIND_JOB_SERVICE" >
        <meta-data
            android:name="immediateScanJobId"
            android:value="208352939" />
        <meta-data
            android:name="periodicScanJobId"
            android:value="208352940" />
    </service>
    <service
        android:name="org.altbeacon.bluetooth.BluetoothTestJob"
        android:exported="false"
        android:permission="android.permission.BIND_JOB_SERVICE" >
        <meta-data
            android:name="jobId"
            android:value="1799803768" />
    </service>
    <service
        android:name="com.google.firebase.components.ComponentDiscoveryService"
        android:directBootAware="true"
        android:exported="false" >
        <meta-data
            android:name="com.google.firebase.components:com.google.firebase.remoteconfig.RemoteConfigRegistrar"
            android:value="com.google.firebase.components.ComponentRegistrar" />
        <meta-data
            android:name="com.google.firebase.components:com.google.firebase.messaging.FirebaseMessagingRegistrar"
            android:value="com.google.firebase.components.ComponentRegistrar" />
        <meta-data
            android:name="com.google.firebase.components:com.google.firebase.crashlytics.CrashlyticsRegistrar"
            android:value="com.google.firebase.components.ComponentRegistrar" />
        <meta-data
            android:name="com.google.firebase.components:com.google.firebase.analytics.connector.internal.AnalyticsConnectorRegistrar"
            android:value="com.google.firebase.components.ComponentRegistrar" />
        <meta-data
            android:name="com.google.firebase.components:com.google.firebase.installations.FirebaseInstallationsRegistrar"
            android:value="com.google.firebase.components.ComponentRegistrar" />
        <meta-data
            android:name="com.google.firebase.components:com.google.firebase.abt.component.AbtRegistrar"
            android:value="com.google.firebase.components.ComponentRegistrar" />
        <meta-data
            android:name="com.google.firebase.components:com.google.firebase.datatransport.TransportRegistrar"
            android:value="com.google.firebase.components.ComponentRegistrar" />
    </service>

    <receiver
        android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        </intent-filter>
    </receiver>
    <!--
         FirebaseMessagingService performs security checks at runtime,
         but set to not exported to explicitly avoid allowing another app to call it.
    -->
    <service
        android:name="com.google.firebase.messaging.FirebaseMessagingService"
        android:directBootAware="true"
        android:exported="false" >
        <intent-filter android:priority="-500" >
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    <!--
         The Mixpanel library will automatically attempt to show available in
         app notifications every time a new Activity is displayed. To disable this behavior,
         add the following line. The default value for this option is set to true.
    -->
    <!--
    <meta-data android:name="com.mixpanel.android.MPConfig.AutoShowMixpanelUpdates"
        android:value="false" />
    -->
    <!--
         Set this option to true if you wish for in-app notifications to be displayed without
         being tracked by Mixpanel. This is useful for testing the integration with your Android app.
         The default value is false.
    -->
    <!--
    <meta-data android:name="com.mixpanel.android.MPConfig.TestMode"
        android:value="true" />
    -->
    <!--
         Set the following option to true if you wish to see the debug output from the Mixpanel Android
         library. This may be useful in determining when track calls go out or in-app notifications
         are fetched. The default value is false.
    -->
    <!--
    <meta-data android:name="com.mixpanel.android.MPConfig.EnableDebugLogging"
        android:value="true" />
    -->
    <!--
         This activity allows your application to show Mixpanel takeover in-app notifications.
         If you only wish to show mini in-app notifications, you do not need to declare this Activity.
         You may also specify a different theme to better fit the look and feel of your application.
    -->
    <!--
    <activity android:name="com.mixpanel.android.takeoverinapp.TakeoverInAppActivity"
              android:theme="@style/com_mixpanel_android_TakeoverInAppActivityTheme" />
    -->
    <!-- This service will allow your application to register for and receive Mixpanel push notifications. -->
    <!--
    <service
        android:name="com.mixpanel.android.mpmetrics.MixpanelFCMMessagingService"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>
    -->
    <!-- This activity will allow your application to make tracking calls to the MixpanelAPI for notification interactions -->
    <activity android:name="com.mixpanel.android.mpmetrics.MixpanelNotificationRouteActivity" >
    </activity>

    <receiver android:name="com.mixpanel.android.mpmetrics.MixpanelPushNotificationDismissedReceiver" >
    </receiver> <!-- The activities will be merged into the manifest of the hosting app. -->
    <activity
        android:name="com.google.android.play.core.common.PlayCoreDialogWrapperActivity"
        android:exported="false"
        android:stateNotNeeded="true"
        android:theme="@style/Theme.PlayCore.Transparent" /> <!-- Needs to be explicitly declared on P+ -->
    <uses-library
        android:name="org.apache.http.legacy"
        android:required="false" />

    <activity
        android:name="com.google.android.gms.common.api.GoogleApiActivity"
        android:exported="false"
        android:theme="@android:style/Theme.Translucent.NoTitleBar" />

    <provider
        android:name="com.google.firebase.provider.FirebaseInitProvider"
        android:authorities="com.myzee.witick.debug.firebaseinitprovider"
        android:directBootAware="true"
        android:exported="false"
        android:initOrder="100" />

    <receiver
        android:name="com.google.android.gms.measurement.AppMeasurementReceiver"
        android:enabled="true"
        android:exported="false" >
    </receiver>

    <service
        android:name="com.google.android.gms.measurement.AppMeasurementService"
        android:enabled="true"
        android:exported="false" />
    <service
        android:name="com.google.android.gms.measurement.AppMeasurementJobService"
        android:enabled="true"
        android:exported="false"
        android:permission="android.permission.BIND_JOB_SERVICE" />

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

    <service
        android:name="androidx.room.MultiInstanceInvalidationService"
        android:directBootAware="true"
        android:exported="false" /> <!-- Start the Service if applicable on boot -->
    <receiver android:name="com.instacart.library.truetime.BootCompletedBroadcastReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    <service
        android:name="com.google.android.datatransport.runtime.backends.TransportBackendDiscovery"
        android:exported="false" >
        <meta-data
            android:name="backend:com.google.android.datatransport.cct.CctBackendFactory"
            android:value="cct" />
    </service>

    <provider
        android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer"
        android:authorities="com.myzee.witick.debug.lifecycle-process"
        android:exported="false"
        android:multiprocess="true" />

    <service
        android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
        android:exported="false"
        android:permission="android.permission.BIND_JOB_SERVICE" >
    </service>

    <receiver
        android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.AlarmManagerSchedulerBroadcastReceiver"
        android:exported="false" />
</application>

`

@tonynguyen0523
Copy link

I am experiencing the same thing.

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference at org.altbeacon.beacon.service.BeaconService.getManifestMetadataValue(BeaconService.java:284) at org.altbeacon.beacon.service.BeaconService.onCreate(BeaconService.java:228) at android.app.ActivityThread.handleCreateService(ActivityThread.java:4512) at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2160)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loopOnce(Looper.java:201)  at android.os.Looper.loop(Looper.java:288)  at android.app.ActivityThread.main(ActivityThread.java:7892)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) 

@FabienWitick
Copy link

FabienWitick commented Jun 24, 2022

After checking the library code and debugging process, I figured that longScanForcingEnabled is missing from the BeaconService metadata. This is what produce the NullPointerException.
If I put <meta-data android:name="longScanForcingEnabled" android:value="false" /> in the manifest for this service, everything works fine.

@davidgyoung
Copy link
Member

davidgyoung commented Jun 24, 2022

@tonynguyen0523 and @FabienWitick, please note that what you two describe has a different stack trace than the one in the issue that opened this question, so I am not certain it is the same issue.

@DarrenMiddleton, can you please try this same workaround to see if it solves the problem for your stack trace as well? Just add this to your app's AndroidManifest.xml:

<service android:name="org.altbeacon.beacon.service.BeaconService"
        tools:node="replace">
        <meta-data android:name="longScanForcingEnabled" android:value="true"/>
 </service>

Run the app, and report back whether your crash goes away.

@FabienWitick
Copy link

@davidgyoung I think this is the same stack trace. The stack posted by @tonynguyen0523 is the cause of the RuntimeException posted by @DarrenMiddleton. I personally have the exact same stack trace on crashlytics.

@davidgyoung
Copy link
Member

Here's a candidate fix: #1095. I am putting this into a beta release now, 2.19.5-beta7. If anyone on this thread with an Android 13 install handy can try that library version and confirm if the crash goes away, I would appreciate it. The fix looks pretty straightforward. It will take about an hour for the beta release to show up on Maven central.

@davidgyoung
Copy link
Member

2.19.5-beta7 is now available on Maven Central.

@FabienWitick
Copy link

FabienWitick commented Jun 27, 2022

Just tried 2.19.5-beta7, it seems to work for me. Thank you for this new build @davidgyoung. Do you think we can use this version for production? Or do we stick to this fix?

@davidgyoung
Copy link
Member

OK, thanks for the confirmation, @FabienWitick. I will merge this in and it will be included in the next non-beta release as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants