Skip to content

Commit a85b96b

Browse files
committed
[Android] update audio notification.
1 parent dd226e6 commit a85b96b

8 files changed

Lines changed: 207 additions & 85 deletions

File tree

Android/APIExample-Audio/app/src/main/java/io/agora/api/example/examples/basic/JoinChannelAudio.java

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import android.content.pm.ServiceInfo;
1414
import android.graphics.Bitmap;
1515
import android.graphics.BitmapFactory;
16+
import android.graphics.Color;
17+
import android.graphics.drawable.Icon;
1618
import android.os.Build;
1719
import android.os.Bundle;
1820
import android.os.Handler;
@@ -322,11 +324,14 @@ public void onPause() {
322324

323325
private void startRecordingService() {
324326
if (joined) {
325-
Intent intent = new Intent(requireContext(), LocalRecordingService.class);
326-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
327-
requireContext().startForegroundService(intent);
328-
} else {
329-
requireContext().startService(intent);
327+
Context context = getContext();
328+
if (context != null) {
329+
Intent intent = new Intent(context, LocalRecordingService.class);
330+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
331+
context.startForegroundService(intent);
332+
} else {
333+
context.startService(intent);
334+
}
330335
}
331336
}
332337
}
@@ -347,8 +352,11 @@ public void onResume() {
347352
}
348353

349354
private void stopRecordingService() {
350-
Intent intent = new Intent(requireContext(), LocalRecordingService.class);
351-
requireContext().stopService(intent);
355+
Context context = getContext();
356+
if (context != null) {
357+
Intent intent = new Intent(context, LocalRecordingService.class);
358+
requireContext().stopService(intent);
359+
}
352360
}
353361

354362
@Override
@@ -665,8 +673,8 @@ public void onAudioRouteChanged(int routing) {
665673
* And the android:foregroundServiceType should be microphone.
666674
*/
667675
public static class LocalRecordingService extends Service {
668-
private static final int NOTIFICATION_ID = 1234567800;
669-
private static final String CHANNEL_ID = "audio_channel_id";
676+
private static final int NOTIFICATION_ID = 1234567900;
677+
private static final String CHANNEL_ID = "api_audio_channel_id";
670678

671679

672680
@Override
@@ -707,28 +715,38 @@ private Notification getDefaultNotification() {
707715
icon = R.mipmap.ic_launcher;
708716
}
709717

710-
if (Build.VERSION.SDK_INT >= 26) {
718+
Intent intent = new Intent(this, MainActivity.class);
719+
intent.setAction("io.agora.api.example.ACTION_NOTIFICATION_CLICK");
720+
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
721+
int requestCode = (int) System.currentTimeMillis();
722+
723+
PendingIntent activityPendingIntent = PendingIntent.getActivity(
724+
this, requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
725+
);
726+
727+
Notification.Builder builder;
728+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
711729
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_DEFAULT);
712730
NotificationManager mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
713731
mNotificationManager.createNotificationChannel(mChannel);
732+
builder = new Notification.Builder(this, CHANNEL_ID);
733+
} else {
734+
builder = new Notification.Builder(this);
714735
}
715736

716-
PendingIntent activityPendingIntent;
717-
Intent intent = new Intent();
718-
intent.setClass(this, MainActivity.class);
719-
activityPendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
720-
721-
Notification.Builder builder = new Notification.Builder(this)
722-
.addAction(icon, "Back to app", activityPendingIntent)
723-
.setContentText("Agora Recording ...")
737+
builder.setContentTitle("Agora Recording ...")
738+
.setContentText("Tap here to return to the app.")
739+
.setContentIntent(activityPendingIntent)
740+
.setAutoCancel(true)
724741
.setOngoing(true)
725742
.setPriority(Notification.PRIORITY_HIGH)
726743
.setSmallIcon(icon)
727-
.setTicker(name)
744+
.setVisibility(Notification.VISIBILITY_PUBLIC)
728745
.setWhen(System.currentTimeMillis());
729-
if (Build.VERSION.SDK_INT >= 26) {
730-
builder.setChannelId(CHANNEL_ID);
731-
}
746+
747+
Icon iconObj = Icon.createWithResource(this, icon);
748+
Notification.Action action = new Notification.Action.Builder(iconObj, "Return to the app", activityPendingIntent).build();
749+
builder.addAction(action);
732750

733751
return builder.build();
734752
}

Android/APIExample/app/src/main/java/io/agora/api/example/MainActivity.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.agora.api.example;
22

3+
import android.content.Intent;
34
import android.os.Bundle;
45

56
import androidx.appcompat.app.AppCompatActivity;
@@ -26,6 +27,21 @@ protected void onCreate(Bundle savedInstanceState) {
2627
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
2728
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
2829
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
30+
31+
handleIntent(getIntent());
32+
}
33+
34+
@Override
35+
protected void onNewIntent(Intent intent) {
36+
super.onNewIntent(intent);
37+
handleIntent(intent);
38+
}
39+
40+
private void handleIntent(Intent intent) {
41+
if (intent != null) {
42+
// 处理从通知栏启动的逻辑
43+
// 可以添加特定的标志来识别是否是从通知栏启动
44+
}
2945
}
3046

3147
@Override

Android/APIExample/app/src/main/java/io/agora/api/example/examples/advanced/ScreenSharing.java

Lines changed: 83 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import android.media.projection.MediaProjectionManager;
1414
import android.os.Build;
1515
import android.os.Bundle;
16+
import android.provider.Settings;
1617
import android.util.DisplayMetrics;
1718
import android.util.Log;
1819
import android.view.LayoutInflater;
@@ -32,14 +33,15 @@
3233
import androidx.activity.result.contract.ActivityResultContracts;
3334
import androidx.annotation.NonNull;
3435
import androidx.annotation.Nullable;
36+
import androidx.appcompat.app.AlertDialog;
37+
import androidx.core.app.NotificationManagerCompat;
3538

3639
import io.agora.api.example.MainApplication;
3740
import io.agora.api.example.R;
3841
import io.agora.api.example.annotation.Example;
3942
import io.agora.api.example.common.BaseFragment;
4043
import io.agora.api.example.service.MediaProjectionService;
4144
import io.agora.api.example.utils.CommonUtil;
42-
import io.agora.api.example.utils.PermissonUtils;
4345
import io.agora.api.example.utils.TokenUtils;
4446
import io.agora.rtc2.ChannelMediaOptions;
4547
import io.agora.rtc2.Constants;
@@ -52,6 +54,9 @@
5254
import io.agora.rtc2.video.VideoCanvas;
5355
import io.agora.rtc2.video.VideoEncoderConfiguration;
5456

57+
import java.lang.reflect.Field;
58+
import java.lang.reflect.Method;
59+
5560
/**
5661
* This example demonstrates how video can be flexibly switched between the camera stream and the
5762
* screen share stream during an audio-video call.
@@ -86,7 +91,6 @@ public class ScreenSharing extends BaseFragment implements View.OnClickListener,
8691
private final ActivityResultLauncher<Intent> mediaProjectionLauncher = registerForActivityResult(
8792
new ActivityResultContracts.StartActivityForResult(),
8893
result -> {
89-
Log.d(TAG, "result-------------------result.getResultCode(): " + result.getResultCode());
9094
if (result.getResultCode() == Activity.RESULT_OK) {
9195
try {
9296
mediaProjection[0] = mediaProjectionManager
@@ -118,7 +122,7 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat
118122
join.setOnClickListener(this);
119123

120124
screenPreview = view.findViewById(R.id.screen_preview);
121-
externalMediaPro = view.findViewById(R.id.media_projection_external);
125+
//externalMediaPro = view.findViewById(R.id.media_projection_external);
122126
screenAudio = view.findViewById(R.id.screen_audio);
123127
screenAudioVolume = view.findViewById(R.id.screen_audio_volume);
124128
screenScenarioType = view.findViewById(R.id.spinner_screen_scenario_type);
@@ -185,11 +189,35 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
185189
e.printStackTrace();
186190
getActivity().onBackPressed();
187191
}
192+
enableNotifications();
193+
}
194+
195+
private void enableNotifications() {
196+
if (NotificationManagerCompat.from(requireContext()).areNotificationsEnabled()) {
197+
Log.d(TAG, "Notifications enable!");
198+
return;
199+
}
200+
Log.d(TAG, "Notifications not enable!");
201+
new AlertDialog.Builder(requireContext())
202+
.setTitle("Tip")
203+
.setMessage(R.string.notifications_enable_screen_tip)
204+
.setPositiveButton(R.string.setting, (dialog, which) -> {
205+
Intent intent = new Intent();
206+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
207+
intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
208+
intent.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().getPackageName());
209+
intent.putExtra(Settings.EXTRA_CHANNEL_ID, requireContext().getApplicationInfo().uid);
210+
} else {
211+
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
212+
}
213+
startActivity(intent);
214+
dialog.dismiss();
215+
})
216+
.show();
188217
}
189218

190219
@Override
191220
public void onDestroy() {
192-
stopService();
193221
/*leaveChannel and Destroy the RtcEngine instance*/
194222
if (engine != null) {
195223
engine.leaveChannel();
@@ -219,8 +247,23 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
219247
}
220248
screenCaptureParameters.captureAudio = checked;
221249
engine.updateScreenCaptureParameters(screenCaptureParameters);
222-
} else if (compoundButton == externalMediaPro) {
250+
} /*else if (compoundButton == externalMediaPro) {
251+
}*/
252+
}
253+
254+
@Override
255+
protected void onBackPressed() {
256+
joined = false;
257+
stopMediaProjectionService();
258+
/*leaveChannel and Destroy the RtcEngine instance*/
259+
if (engine != null) {
260+
engine.leaveChannel();
261+
engine.stopScreenCapture();
262+
engine.stopPreview();
223263
}
264+
handler.post(RtcEngine::destroy);
265+
engine = null;
266+
super.onBackPressed();
224267
}
225268

226269
@Override
@@ -231,15 +274,12 @@ public void onClick(View v) {
231274
// call when join button hit
232275
channelId = et_channel.getText().toString();
233276
// Check permission
234-
checkOrRequestPermisson(new PermissonUtils.PermissionResultCallback() {
235-
@Override
236-
public void onPermissionsResult(boolean allPermissionsGranted, String[] permissions, int[] grantResults) {
237-
if (allPermissionsGranted) {
238-
if (externalMediaPro.isChecked()) {
239-
requestScreenCapture();
240-
} else {
241-
joinChannel();
242-
}
277+
checkOrRequestPermisson((allPermissionsGranted, permissions, grantResults) -> {
278+
if (allPermissionsGranted) {
279+
if (externalMediaPro.isChecked()) {
280+
requestScreenCapture();
281+
} else {
282+
joinChannel();
243283
}
244284
}
245285
});
@@ -278,24 +318,41 @@ private void stopScreenSharePreview() {
278318
engine.stopPreview(Constants.VideoSourceType.VIDEO_SOURCE_SCREEN_PRIMARY);
279319
}
280320

281-
private void startService() {
282-
// if (joined) {
283-
Intent intent = new Intent(requireContext(), MediaProjectionService.class);
284-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
285-
requireContext().startForegroundService(intent);
286-
} else {
287-
requireContext().startService(intent);
321+
@Override
322+
public void onPause() {
323+
super.onPause();
324+
// startMediaProjectionService();
325+
}
326+
327+
@Override
328+
public void onResume() {
329+
super.onResume();
330+
// stopMediaProjectionService();
331+
}
332+
333+
private void startMediaProjectionService() {
334+
if (joined) {
335+
Context context = getContext();
336+
if (context != null) {
337+
Intent intent = new Intent(context, MediaProjectionService.class);
338+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
339+
context.startForegroundService(intent);
340+
} else {
341+
context.startService(intent);
342+
}
343+
}
288344
}
289-
// }
290345
}
291346

292-
private void stopService() {
293-
Intent serviceIntent = new Intent(getContext(), MediaProjectionService.class);
294-
getContext().stopService(serviceIntent);
347+
private void stopMediaProjectionService() {
348+
Context context = getContext();
349+
if (context != null) {
350+
Intent serviceIntent = new Intent(context, MediaProjectionService.class);
351+
context.stopService(serviceIntent);
352+
}
295353
}
296354

297355
private void requestScreenCapture() {
298-
startService();
299356
Intent intent = mediaProjectionManager.createScreenCaptureIntent();
300357
mediaProjectionLauncher.launch(intent);
301358
}
@@ -519,7 +576,6 @@ public void onUserOffline(int uid, int reason) {
519576

520577
private void leaveChannel() {
521578
externalMediaPro.setEnabled(true);
522-
stopService();
523579
joined = false;
524580
join.setText(getString(R.string.join));
525581
fl_local.removeAllViews();

0 commit comments

Comments
 (0)