Skip to content

Commit

Permalink
Merge pull request #1516 from BlueBubblesApp/development
Browse files Browse the repository at this point in the history
v1.5.0 release (stable)
  • Loading branch information
zlshames authored Sep 9, 2021
2 parents 82251a6 + eade249 commit d2c425a
Show file tree
Hide file tree
Showing 121 changed files with 7,257 additions and 4,711 deletions.
2 changes: 2 additions & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ dependencies {
//for location sending
implementation "com.google.android.gms:play-services-location:18.0.0"

// for album art color
implementation 'androidx.palette:palette:1.0.0'

// Add the SDK for Firebase Cloud Messaging
implementation 'com.google.firebase:firebase-messaging:22.0.0'
Expand Down
13 changes: 11 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>

<application
android:allowBackup="false"
Expand Down Expand Up @@ -66,6 +67,14 @@
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="false"/>

<service android:name=".services.CustomNotificationListenerService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:exported="false">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>

<provider
android:name="com.google.firebase.provider.FirebaseInitProvider"
android:authorities="${applicationId}.firebaseinitprovider"
Expand Down Expand Up @@ -151,9 +160,9 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- <meta-data
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/> -->
android:resource="@xml/automotive_app_desc"/>

</application>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public class MainActivity extends FlutterFragmentActivity {

public static int PICK_IMAGE = 1000;
public static int OPEN_CAMERA = 2000;
public static int NOTIFICATION_SETTINGS = 3000;
public MethodChannel.Result result = null;


Expand Down Expand Up @@ -128,6 +129,8 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("OPEN_CAMERA", "Something went wrong");
result.success(null);
}
} else if (requestCode == NOTIFICATION_SETTINGS) {
result.success(null);
}
}

Expand Down Expand Up @@ -304,6 +307,7 @@ protected void onStart() {
@Override
protected void onDestroy() {
Log.d("MainActivity", "Removing Activity from memory");
new MethodChannel(engine.getDartExecutor().getBinaryMessenger(), CHANNEL).invokeMethod("remove-sendPort", null);
engine = null;
super.onDestroy();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import android.app.AlarmManager;
import android.content.Context;
import android.os.Build;
import android.content.Intent;
import android.provider.Settings;

import androidx.annotation.RequiresApi;

Expand All @@ -20,6 +22,7 @@
import com.bluebubbles.messaging.method_call_handler.handlers.GetLastLocation;
import com.bluebubbles.messaging.method_call_handler.handlers.GetServerUrl;
import com.bluebubbles.messaging.method_call_handler.handlers.InitializeBackgroundHandle;
import com.bluebubbles.messaging.method_call_handler.handlers.MediaSessionListener;
import com.bluebubbles.messaging.method_call_handler.handlers.NewMessageNotification;
import com.bluebubbles.messaging.method_call_handler.handlers.OpenCamera;
import com.bluebubbles.messaging.method_call_handler.handlers.OpenFile;
Expand All @@ -32,6 +35,7 @@
import com.bluebubbles.messaging.method_call_handler.handlers.OpenContactForm;
import com.bluebubbles.messaging.method_call_handler.handlers.ViewContactForm;
import com.bluebubbles.messaging.workers.DartWorker;
import static com.bluebubbles.messaging.MainActivity.engine;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
Expand Down Expand Up @@ -96,6 +100,21 @@ public static void methodCallHandler(MethodCall call, MethodChannel.Result resul
new FailedToSend(context, call, result).Handle();
} else if (call.method.equals(ClearFailedToSend.TAG)) {
new ClearFailedToSend(context, call, result).Handle();
} else if (call.method.equals("start-notif-listener")) {
if (Settings.Secure.getString(context.getContentResolver(),"enabled_notification_listeners").contains(context.getPackageName()) && engine != null) {
new MediaSessionListener(context, call, result).Handle();
} else {
result.error("could_not_initialize", "Failed to initialize, permission not granted", "");
}
} else if (call.method.equals("request-notif-permission")) {
if (Settings.Secure.getString(context.getContentResolver(),"enabled_notification_listeners").contains(context.getPackageName())) {
result.success("");
} else {
MainActivity activity = (MainActivity) context;
activity.result = result;
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
activity.startActivityForResult(intent, 3000);
}
} else {
result.notImplemented();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.media.AudioAttributes;
import android.os.Build;
import android.net.Uri;
import android.util.Log;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
Expand All @@ -23,11 +26,11 @@ public CreateNotificationChannel(Context context, MethodCall call, MethodChanne

@Override
public void Handle() {
createNotificationChannel(call.argument("channel_name"), call.argument("channel_description"), call.argument("CHANNEL_ID"), context);
createNotificationChannel(call.argument("channel_name"), call.argument("channel_description"), call.argument("CHANNEL_ID"), call.argument("sound"), context);
result.success("");
}

public static void createNotificationChannel(String channel_name, String channel_description, String CHANNEL_ID, Context context) {
public static void createNotificationChannel(String channel_name, String channel_description, String CHANNEL_ID, String soundPath, Context context) {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Expand All @@ -38,6 +41,14 @@ public static void createNotificationChannel(String channel_name, String channel
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
if (soundPath != null) {
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build();
int soundResourceId = context.getResources().getIdentifier(soundPath, "raw", context.getPackageName());
channel.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + soundResourceId), audioAttributes);
}
NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package com.bluebubbles.messaging.method_call_handler.handlers;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.media.session.MediaController;
import android.media.MediaMetadata;
import android.media.session.PlaybackState;
import android.media.session.MediaSessionManager;
import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
import android.os.Build;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;

import java.util.HashMap;
import java.util.List;
import java.io.ByteArrayOutputStream;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.palette.graphics.Palette;
import com.bluebubbles.messaging.services.CustomNotificationListenerService;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import static com.bluebubbles.messaging.MainActivity.engine;
import static com.bluebubbles.messaging.MainActivity.CHANNEL;


@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MediaSessionListener implements OnActiveSessionsChangedListener, Handler {

private Context context;
private MethodCall call;
private MethodChannel.Result result;
private List<MediaController> oldControllers;
private MediaController.Callback callback;
private MethodChannel backgroundChannel;

public MediaSessionListener(Context context, MethodCall call, MethodChannel.Result result) {
this.context = context;
this.call = call;
this.result = result;
}


@Override
public void Handle() {
backgroundChannel = new MethodChannel(engine.getDartExecutor().getBinaryMessenger(), CHANNEL);
MediaSessionManager manager = (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
if (null == manager) {
result.error("could_not_initialize", "Failed to initialize, manager == null", "");
}
callback = new MediaController.Callback() {
@Override
public void onMetadataChanged(MediaMetadata metadata) {
String title = metadata.getString(MediaMetadata.METADATA_KEY_TITLE);
if (title == null) {
title = "Unknown";
}
Bitmap icon = metadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
Bitmap icon2 = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
Log.d("BlueBubblesApp", "Getting media metadata for media " + title);
HashMap<String, Object> input = new HashMap<>();
Palette p = null;
if (icon != null) {
p = Palette.from(icon).generate();
} else if (icon2 != null) {
p = Palette.from(icon2).generate();
}
if (p != null) {
int lightBg = p.getLightVibrantColor(Color.WHITE);
int darkBg = p.getDarkMutedColor(Color.BLACK);
int primary;
double lightBgPercent = 0.5;
double darkBgPercent = 0.5;
double primaryPercent = 0.5;
String primaryFrom = "none";
if (p.getVibrantColor(0xFF2196F3) != 0xFF2196F3) {
primary = p.getVibrantColor(0xFF2196F3);
primaryFrom = "vibrant";
} else if (p.getMutedColor(0xFF2196F3) != 0xFF2196F3) {
primary = p.getMutedColor(0xFF2196F3);
primaryFrom = "muted";
} else if (p.getLightMutedColor(0xFF2196F3) != 0xFF2196F3) {
primary = p.getLightMutedColor(0xFF2196F3);
primaryFrom = "lightMuted";
} else {
primary = 0xFF2196F3;
primaryFrom = "none";
}
if (p.getLightVibrantSwatch() != null) {
lightBgPercent = p.getLightVibrantSwatch().getPopulation();
}
if (p.getDarkMutedSwatch() != null) {
darkBgPercent = p.getDarkMutedSwatch().getPopulation();
}
if (primaryFrom == "vibrant" && p.getVibrantSwatch() != null) {
primaryPercent = p.getVibrantSwatch().getPopulation();
} else if (primaryFrom == "muted" && p.getMutedSwatch() != null) {
primaryPercent = p.getMutedSwatch().getPopulation();
} else if (primaryFrom == "lightMuted" && p.getLightMutedSwatch() != null) {
primaryPercent = p.getLightMutedSwatch().getPopulation();
}
Log.d("BlueBubblesApp", "Dominant color found (for debugging only): " + Integer.toString(p.getDominantColor(Color.BLACK)));
input.put("lightBg", lightBg);
input.put("darkBg", darkBg);
input.put("primary", primary);
input.put("lightBgPercent", lightBgPercent);
input.put("darkBgPercent", darkBgPercent);
input.put("primaryPercent", primaryPercent);
Log.d("BlueBubblesApp", "Sending media metadata for media " + title);
backgroundChannel.invokeMethod("media-colors", input);
}
}
};
List<MediaController> controllers = manager.getActiveSessions(new ComponentName(context, CustomNotificationListenerService.class));
oldControllers = controllers;
if (null != controllers && controllers.size() != 0) {
for (MediaController controller : controllers) {
controller.registerCallback(callback);
}
}
manager.addOnActiveSessionsChangedListener(MediaSessionListener.this, new ComponentName(context, CustomNotificationListenerService.class));
result.success("");
}

@Override
public void onActiveSessionsChanged(@Nullable List<MediaController> controllers) {

if (null == controllers || controllers.size() == 0) {
return;
}

for (MediaController controller : oldControllers) {
controller.unregisterCallback(callback);
}
oldControllers = controllers;
for (MediaController controller : controllers) {
controller.registerCallback(callback);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import android.net.Uri;
import android.service.notification.StatusBarNotification;

import androidx.annotation.RequiresApi;
Expand Down Expand Up @@ -81,6 +82,7 @@ public void Handle() {
Integer notificationVisibility = (Integer) call.argument("visibility");
Integer notificationId = (Integer) call.argument("notificationId");
Integer summaryId = (Integer) call.argument("summaryId");
String soundPath = (String) call.argument("sound");

// Find any notifications that already exist for the chat
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Expand Down Expand Up @@ -283,6 +285,12 @@ public void Handle() {
// Set the color. This is the blue primary color
.setColor(4888294);

// Set the sound of the notification (Android 7 and below)
if (soundPath != "default") {
int soundResourceId = context.getResources().getIdentifier(soundPath, "raw", context.getPackageName());
notificationBuilder.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/" + soundResourceId));
}

// Disable the alert if it's from you
notificationBuilder.setOnlyAlertOnce(messageIsFromMe);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.bluebubbles.messaging.services;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.util.Log;

public class CustomNotificationListenerService extends NotificationListenerService {

}
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ public void onMethodCall(MethodCall call, @NonNull Result result) {
*/
public void startBackgroundIsolate() {
if (isNotRunning()) {
long callbackHandle = getPluginCallbackHandle();
if (callbackHandle != 0) {
Long callbackHandle = getPluginCallbackHandle();
if (callbackHandle != null && callbackHandle != 0) {
startBackgroundIsolate(callbackHandle, null);
}
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added android/app/src/main/res/raw/raspberry.wav
Binary file not shown.
Binary file added android/app/src/main/res/raw/sugarfree.wav
Binary file not shown.
Binary file added android/app/src/main/res/raw/twig.wav
Binary file not shown.
Binary file added android/app/src/main/res/raw/walrus.wav
Binary file not shown.
Loading

0 comments on commit d2c425a

Please sign in to comment.