Rapsssito / react-native-background-actions

React Native background service library for running background tasks forever in Android & iOS.
MIT License
818 stars 117 forks source link

App crashes when the app goes into the background while sharing the screen. #234

Open vishalyad16 opened 3 months ago

vishalyad16 commented 3 months ago
          @Rapsssito  It still crashes when the app goes into the background while sharing the screen.

"react-native-background-actions": "^4.0.1",

buildToolsVersion = "34.0.0" minSdkVersion = 23 compileSdkVersion = 34 targetSdkVersion = 34 ndkVersion = "26.2.11394342" kotlinVersion = "1.9.22"

`package com.asterinet.react.bgactions;

import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle;

import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat;

import com.facebook.react.HeadlessJsTaskService; import com.facebook.react.bridge.Arguments; import com.facebook.react.jstasks.HeadlessJsTaskConfig;

final public class RNBackgroundActionsTask extends HeadlessJsTaskService {

public static final int SERVICE_NOTIFICATION_ID = 92901;
private static final String CHANNEL_ID = "RN_BACKGROUND_ACTIONS_CHANNEL";

@SuppressLint("UnspecifiedImmutableFlag")
@NonNull
public static Notification buildNotification(@NonNull Context context, @NonNull final BackgroundTaskOptions bgOptions) {
    // Get info
    final String taskTitle = bgOptions.getTaskTitle();
    final String taskDesc = bgOptions.getTaskDesc();
    final int iconInt = bgOptions.getIconInt();
    final int color = bgOptions.getColor();
    final String linkingURI = bgOptions.getLinkingURI();
    Intent notificationIntent;
    if (linkingURI != null) {
        notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(linkingURI));
    } else {
        //as RN works on single activity architecture - we don't need to find current activity on behalf of react context
        notificationIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
    }
    final PendingIntent contentIntent;
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
        contentIntent = PendingIntent.getActivity(context,0, notificationIntent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_MUTABLE);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
    } else {
        contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    }
    final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
            .setContentTitle(taskTitle)
            .setContentText(taskDesc)
            .setSmallIcon(iconInt)
            .setContentIntent(contentIntent)
            .setOngoing(true)
            .setPriority(NotificationCompat.PRIORITY_MIN)
            .setColor(color);

    final Bundle progressBarBundle = bgOptions.getProgressBar();
    if (progressBarBundle != null) {
        final int progressMax = (int) Math.floor(progressBarBundle.getDouble("max"));
        final int progressCurrent = (int) Math.floor(progressBarBundle.getDouble("value"));
        final boolean progressIndeterminate = progressBarBundle.getBoolean("indeterminate");
        builder.setProgress(progressMax, progressCurrent, progressIndeterminate);
    }
    return builder.build();
}

@Override
protected @Nullable
HeadlessJsTaskConfig getTaskConfig(Intent intent) {
    final Bundle extras = intent.getExtras();
    if (extras != null) {
        return new HeadlessJsTaskConfig(extras.getString("taskName"), Arguments.fromBundle(extras), 0, true);
    }
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    final Bundle extras = intent.getExtras();
    if (extras == null) {
        throw new IllegalArgumentException("Extras cannot be null");
    }
    final BackgroundTaskOptions bgOptions = new BackgroundTaskOptions(extras);
    createNotificationChannel(bgOptions.getTaskTitle(), bgOptions.getTaskDesc()); // Necessary creating channel for API 26+
    // Create the notification
    final Notification notification = buildNotification(this, bgOptions);

    startForeground(SERVICE_NOTIFICATION_ID, notification);
    return super.onStartCommand(intent, flags, startId);
}

private void createNotificationChannel(@NonNull final String taskTitle, @NonNull final String taskDesc) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        final int importance = NotificationManager.IMPORTANCE_LOW;
        final NotificationChannel channel = new NotificationChannel(CHANNEL_ID, taskTitle, importance);
        channel.setDescription(taskDesc);
        final NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

} ` @Rapsssito, I need to release the app on the Play Store with target SDK 34. Please mark this as urgent. Thanks

FATAL EXCEPTION: main Process: com.explorastory, PID: 16580 java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1001, result=-1, data=Intent { (has extras) }} to activity {/io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity}: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION

Originally posted by @vishalyad16 in https://github.com/Rapsssito/react-native-background-actions/issues/223#issuecomment-2252544570

BagasNS commented 3 months ago

try change foregroundServiceType from android:foregroundServiceType="shortService" to android:foregroundServiceType="mediaProjection" then add new permission at your AndroidManifest.xml

<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />

ref: https://developer.android.com/about/versions/14/changes/fgs-types-required#media-projection

vishalyad16 commented 3 months ago

@BagasNS does this solution working for you ?

Hi,

We have already included the permission in the AndroidManifest.xml file. However, the app crashes when we install the APK for the first time and attempt to grant permission to share. The crash occurs when the app goes into the background. Once we reopen the app and attempt to share again, it does not crash.

@Rapsssito Since we need to release this on the Play Store, we have to fix this issue as soon as possible.

Thanks

vishalyad16 commented 2 months ago

@Rapsssito waiting for your response

FATAL EXCEPTION: main Process: com.explorastory, PID: 902 java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1001, result=-1, data=Intent { (has extras) }} to activity {com.explorastory/io.agora.rtc2.extensions.MediaProjectionMgr$LocalScreenCaptureAssistantActivity}: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION at android.app.ActivityThread.deliverResults(ActivityThread.java:5898) at android.app.ActivityThread.handleSendResult(ActivityThread.java:5937) at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:67) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:144) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:101) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2643) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:257) at android.os.Looper.loop(Looper.java:368) at android.app.ActivityThread.main(ActivityThread.java:8839) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:572) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049) Caused by: java.lang.SecurityException: Media projections require a foreground service of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION

vishalyad16 commented 2 months ago

@BagasNS ?

BagasNS commented 2 months ago

@BagasNS ?

please refer to this url https://github.com/Rapsssito/react-native-background-actions/issues/228#issuecomment-2298775963

vishalyad16 commented 1 month ago

Thanks, @BagasNS! The app is no longer crashing, but the microphone isn't working while the app is in the background. However, it functions properly in the foreground, where both camera and microphone permissions are granted. https://github.com/Rapsssito/react-native-background-actions/issues/242#issuecomment-2385632656