feat(android): separate MediaProjection and OngoingConference notifications (#14363)

* feat(android): separate MediaProjection and OngoingConference notifications
pull/14365/head jitsi-meet_9281
Calinteodor 1 year ago committed by GitHub
parent a7b2726ebe
commit ba20fc71a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      android/sdk/src/main/java/org/jitsi/meet/sdk/JitsiMeetMediaProjectionModule.java
  2. 13
      android/sdk/src/main/java/org/jitsi/meet/sdk/JitsiMeetMediaProjectionService.java
  3. 10
      android/sdk/src/main/java/org/jitsi/meet/sdk/JitsiMeetOngoingConferenceService.java
  4. 59
      android/sdk/src/main/java/org/jitsi/meet/sdk/MediaProjectionNotification.java
  5. 45
      android/sdk/src/main/java/org/jitsi/meet/sdk/NotificationUtils.java
  6. 42
      android/sdk/src/main/java/org/jitsi/meet/sdk/OngoingNotification.java
  7. 3
      android/sdk/src/main/res/values/strings.xml

@ -1,5 +1,6 @@
package org.jitsi.meet.sdk;
import android.app.Activity;
import android.content.Context;
import androidx.annotation.NonNull;
@ -23,8 +24,9 @@ class JitsiMeetMediaProjectionModule
@ReactMethod
public void launch() {
Context context = getReactApplicationContext();
Activity currentActivity = getCurrentActivity();
JitsiMeetMediaProjectionService.launch(context);
JitsiMeetMediaProjectionService.launch(context, currentActivity);
}
@ReactMethod

@ -17,6 +17,7 @@
package org.jitsi.meet.sdk;
import android.app.Activity;
import android.app.Notification;
import android.app.Service;
import android.content.ComponentName;
@ -30,7 +31,6 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Random;
/**
* This class implements an Android {@link Service}, a foreground one specifically, and it's
* responsible for presenting an ongoing notification when a conference is in progress.
@ -43,8 +43,9 @@ public class JitsiMeetMediaProjectionService extends Service {
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
public static void launch(Context context) {
OngoingNotification.createOngoingConferenceNotificationChannel();
public static void launch(Context context, Activity currentActivity) {
NotificationUtils.createNotificationChannel(currentActivity);
Intent intent = new Intent(context, JitsiMeetMediaProjectionService.class);
@ -59,12 +60,12 @@ public class JitsiMeetMediaProjectionService extends Service {
} catch (RuntimeException e) {
// Avoid crashing due to ForegroundServiceStartNotAllowedException (API level 31).
// See: https://developer.android.com/guide/components/foreground-services#background-start-restrictions
JitsiMeetLogger.w(TAG + " Ongoing conference service not started", e);
JitsiMeetLogger.w(TAG + "Media projection service not started", e);
return;
}
if (componentName == null) {
JitsiMeetLogger.w(TAG + " Ongoing conference service not started");
JitsiMeetLogger.w(TAG + "Media projection service not started");
}
}
@ -81,7 +82,7 @@ public class JitsiMeetMediaProjectionService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = OngoingNotification.buildOngoingConferenceNotification(null);
Notification notification = MediaProjectionNotification.buildMediaProjectionNotification();
if (notification == null) {
stopSelf();

@ -16,6 +16,7 @@
package org.jitsi.meet.sdk;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
@ -57,7 +58,8 @@ public class JitsiMeetOngoingConferenceService extends Service
public static void launch(Context context, HashMap<String, Object> extraData) {
OngoingNotification.createOngoingConferenceNotificationChannel();
NotificationUtils.createNotificationChannel((Activity) context);
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
@ -94,7 +96,7 @@ public class JitsiMeetOngoingConferenceService extends Service
public void onCreate() {
super.onCreate();
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, this);
if (notification == null) {
stopSelf();
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
@ -134,7 +136,7 @@ public class JitsiMeetOngoingConferenceService extends Service
if (isAudioMuted != null) {
this.isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, this);
if (notification == null) {
stopSelf();
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
@ -220,7 +222,7 @@ public class JitsiMeetOngoingConferenceService extends Service
@Override
public void onReceive(Context context, Intent intent) {
isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted);
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, context);
if (notification == null) {
stopSelf();
JitsiMeetLogger.w(TAG + " Couldn't update service, notification is null");

@ -0,0 +1,59 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import static org.jitsi.meet.sdk.NotificationChannels.ONGOING_CONFERENCE_CHANNEL_ID;
import android.app.Notification;
import android.content.Context;
import androidx.core.app.NotificationCompat;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
/**
* Helper class for creating the media projection notification which is used with
* {@link JitsiMeetMediaProjectionService}.
*/
class MediaProjectionNotification {
private static final String TAG = MediaProjectionNotification.class.getSimpleName();
static Notification buildMediaProjectionNotification() {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
JitsiMeetLogger.d(TAG, " Cannot create notification: no current context");
return null;
}
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, ONGOING_CONFERENCE_CHANNEL_ID);
builder
.setCategory(NotificationCompat.CATEGORY_CALL)
.setContentTitle(context.getString(R.string.media_projection_notification_title))
.setContentText(context.getString(R.string.media_projection_notification_text))
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(false)
.setUsesChronometer(false)
.setAutoCancel(true)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOnlyAlertOnce(true)
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()));
return builder.build();
}
}

@ -0,0 +1,45 @@
package org.jitsi.meet.sdk;
import static org.jitsi.meet.sdk.NotificationChannels.ONGOING_CONFERENCE_CHANNEL_ID;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
class NotificationUtils {
private static final String TAG = NotificationUtils.class.getSimpleName();
static void createNotificationChannel(Activity context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
if (context == null) {
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
return;
}
NotificationManager notificationManager
= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel
= notificationManager.getNotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID);
if (channel != null) {
// The channel was already created, no need to do it again.
return;
}
channel = new NotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID, context.getString(R.string.ongoing_notification_channel_name), NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(false);
channel.enableVibration(false);
channel.setShowBadge(false);
notificationManager.createNotificationChannel(channel);
}
}

@ -19,20 +19,15 @@ package org.jitsi.meet.sdk;
import static org.jitsi.meet.sdk.NotificationChannels.ONGOING_CONFERENCE_CHANNEL_ID;
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.os.Build;
import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.Random;
/**
* Helper class for creating the ongoing notification which is used with
* {@link JitsiMeetOngoingConferenceService}. It allows the user to easily get back to the app
@ -43,37 +38,8 @@ class OngoingNotification {
private static long startingTime = 0;
static void createOngoingConferenceNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
static Notification buildOngoingConferenceNotification(Boolean isMuted, Context context) {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
return;
}
NotificationManager notificationManager
= (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel
= notificationManager.getNotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID);
if (channel != null) {
// The channel was already created, no need to do it again.
return;
}
channel = new NotificationChannel(ONGOING_CONFERENCE_CHANNEL_ID, context.getString(R.string.ongoing_notification_action_unmute), NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(false);
channel.enableVibration(false);
channel.setShowBadge(false);
notificationManager.createNotificationChannel(channel);
}
static Notification buildOngoingConferenceNotification(Boolean isMuted) {
Context context = ReactInstanceManagerHolder.getCurrentActivity();
if (context == null) {
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
return null;
@ -91,7 +57,7 @@ class OngoingNotification {
builder
.setCategory(NotificationCompat.CATEGORY_CALL)
.setContentTitle(context.getString(R.string.ongoing_notification_title))
.setContentText(isMuted != null ? context.getString(R.string.ongoing_notification_text) : context.getString(R.string.ongoing_notification_action_screenshare))
.setContentText(context.getString(R.string.ongoing_notification_text))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setOngoing(true)
@ -102,10 +68,6 @@ class OngoingNotification {
.setOnlyAlertOnce(true)
.setSmallIcon(context.getResources().getIdentifier("ic_notification", "drawable", context.getPackageName()));
if (isMuted == null) {
return builder.build();
}
NotificationCompat.Action hangupAction = createAction(context, JitsiMeetOngoingConferenceService.Action.HANGUP, R.string.ongoing_notification_action_hang_up);
JitsiMeetOngoingConferenceService.Action toggleAudioAction = isMuted

@ -1,11 +1,12 @@
<resources>
<string name="app_name">Jitsi Meet SDK</string>
<string name="dropbox_app_key"></string>
<string name="media_projection_notification_title">Media projection</string>
<string name="media_projection_notification_text">You are currently sharing your screen.</string>
<string name="ongoing_notification_title">Ongoing meeting</string>
<string name="ongoing_notification_text">You are currently in a meeting. Tap to return to it.</string>
<string name="ongoing_notification_action_hang_up">Hang up</string>
<string name="ongoing_notification_action_mute">Mute</string>
<string name="ongoing_notification_action_screenshare">You are currently screen-sharing. Tap to return to the meeting.</string>
<string name="ongoing_notification_action_unmute">Unmute</string>
<string name="ongoing_notification_channel_name">Ongoing Conference Notifications</string>
</resources>

Loading…
Cancel
Save