Rewrite the notification code in Kotlin
This commit is contained in:
parent
1771c0e1b6
commit
864b868f45
@ -175,6 +175,18 @@ class MyHomePage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
child: const Text('Show messaging notification'),
|
child: const Text('Show messaging notification'),
|
||||||
),
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
print(await MoxplatformPlugin.platform.getPersistentDataPath());
|
||||||
|
},
|
||||||
|
child: const Text('Get data directory'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
print(await MoxplatformPlugin.platform.getCacheDataPath());
|
||||||
|
},
|
||||||
|
child: const Text('Get cache directory'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -2,8 +2,8 @@ import 'package:moxplatform_platform_interface/moxplatform_platform_interface.da
|
|||||||
|
|
||||||
class MoxplatformPlugin {
|
class MoxplatformPlugin {
|
||||||
static IsolateHandler get handler => MoxplatformInterface.handler;
|
static IsolateHandler get handler => MoxplatformInterface.handler;
|
||||||
static MediaScannerImplementation get media => MoxplatformInterface.media;
|
|
||||||
static CryptographyImplementation get crypto => MoxplatformInterface.crypto;
|
static CryptographyImplementation get crypto => MoxplatformInterface.crypto;
|
||||||
static ContactsImplementation get contacts => MoxplatformInterface.contacts;
|
static ContactsImplementation get contacts => MoxplatformInterface.contacts;
|
||||||
static NotificationsImplementation get notifications => MoxplatformInterface.notifications;
|
static NotificationsImplementation get notifications => MoxplatformInterface.notifications;
|
||||||
|
static PlatformImplementation get platform => MoxplatformInterface.platform;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
/** Generated class from Pigeon. */
|
/** Generated class from Pigeon. */
|
||||||
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"})
|
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"})
|
||||||
public class Notifications {
|
public class Api {
|
||||||
|
|
||||||
/** Error class for passing custom error details to Flutter via a thrown PlatformException. */
|
/** Error class for passing custom error details to Flutter via a thrown PlatformException. */
|
||||||
public static class FlutterError extends RuntimeException {
|
public static class FlutterError extends RuntimeException {
|
||||||
@ -416,10 +416,10 @@ public class Notifications {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NotificationsImplementationApiCodec extends StandardMessageCodec {
|
private static class MoxplatformApiCodec extends StandardMessageCodec {
|
||||||
public static final NotificationsImplementationApiCodec INSTANCE = new NotificationsImplementationApiCodec();
|
public static final MoxplatformApiCodec INSTANCE = new MoxplatformApiCodec();
|
||||||
|
|
||||||
private NotificationsImplementationApiCodec() {}
|
private MoxplatformApiCodec() {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
|
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
|
||||||
@ -453,22 +453,28 @@ public class Notifications {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||||
public interface NotificationsImplementationApi {
|
public interface MoxplatformApi {
|
||||||
|
|
||||||
void createNotificationChannel(@NonNull String title, @NonNull String id, @NonNull Boolean urgent);
|
void createNotificationChannel(@NonNull String title, @NonNull String id, @NonNull Boolean urgent);
|
||||||
|
|
||||||
void showMessagingNotification(@NonNull MessagingNotification notification);
|
void showMessagingNotification(@NonNull MessagingNotification notification);
|
||||||
|
|
||||||
/** The codec used by NotificationsImplementationApi. */
|
@NonNull
|
||||||
|
String getPersistentDataPath();
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
String getCacheDataPath();
|
||||||
|
|
||||||
|
/** The codec used by MoxplatformApi. */
|
||||||
static @NonNull MessageCodec<Object> getCodec() {
|
static @NonNull MessageCodec<Object> getCodec() {
|
||||||
return NotificationsImplementationApiCodec.INSTANCE;
|
return MoxplatformApiCodec.INSTANCE;
|
||||||
}
|
}
|
||||||
/**Sets up an instance of `NotificationsImplementationApi` to handle messages through the `binaryMessenger`. */
|
/**Sets up an instance of `MoxplatformApi` to handle messages through the `binaryMessenger`. */
|
||||||
static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable NotificationsImplementationApi api) {
|
static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable MoxplatformApi api) {
|
||||||
{
|
{
|
||||||
BasicMessageChannel<Object> channel =
|
BasicMessageChannel<Object> channel =
|
||||||
new BasicMessageChannel<>(
|
new BasicMessageChannel<>(
|
||||||
binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.NotificationsImplementationApi.createNotificationChannel", getCodec());
|
binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.createNotificationChannel", getCodec());
|
||||||
if (api != null) {
|
if (api != null) {
|
||||||
channel.setMessageHandler(
|
channel.setMessageHandler(
|
||||||
(message, reply) -> {
|
(message, reply) -> {
|
||||||
@ -494,7 +500,7 @@ public class Notifications {
|
|||||||
{
|
{
|
||||||
BasicMessageChannel<Object> channel =
|
BasicMessageChannel<Object> channel =
|
||||||
new BasicMessageChannel<>(
|
new BasicMessageChannel<>(
|
||||||
binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.NotificationsImplementationApi.showMessagingNotification", getCodec());
|
binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.showMessagingNotification", getCodec());
|
||||||
if (api != null) {
|
if (api != null) {
|
||||||
channel.setMessageHandler(
|
channel.setMessageHandler(
|
||||||
(message, reply) -> {
|
(message, reply) -> {
|
||||||
@ -505,6 +511,50 @@ public class Notifications {
|
|||||||
api.showMessagingNotification(notificationArg);
|
api.showMessagingNotification(notificationArg);
|
||||||
wrapped.add(0, null);
|
wrapped.add(0, null);
|
||||||
}
|
}
|
||||||
|
catch (Throwable exception) {
|
||||||
|
ArrayList<Object> wrappedError = wrapError(exception);
|
||||||
|
wrapped = wrappedError;
|
||||||
|
}
|
||||||
|
reply.reply(wrapped);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BasicMessageChannel<Object> channel =
|
||||||
|
new BasicMessageChannel<>(
|
||||||
|
binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getPersistentDataPath", getCodec());
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler(
|
||||||
|
(message, reply) -> {
|
||||||
|
ArrayList<Object> wrapped = new ArrayList<Object>();
|
||||||
|
try {
|
||||||
|
String output = api.getPersistentDataPath();
|
||||||
|
wrapped.add(0, output);
|
||||||
|
}
|
||||||
|
catch (Throwable exception) {
|
||||||
|
ArrayList<Object> wrappedError = wrapError(exception);
|
||||||
|
wrapped = wrappedError;
|
||||||
|
}
|
||||||
|
reply.reply(wrapped);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
BasicMessageChannel<Object> channel =
|
||||||
|
new BasicMessageChannel<>(
|
||||||
|
binaryMessenger, "dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getCacheDataPath", getCodec());
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler(
|
||||||
|
(message, reply) -> {
|
||||||
|
ArrayList<Object> wrapped = new ArrayList<Object>();
|
||||||
|
try {
|
||||||
|
String output = api.getCacheDataPath();
|
||||||
|
wrapped.add(0, output);
|
||||||
|
}
|
||||||
catch (Throwable exception) {
|
catch (Throwable exception) {
|
||||||
ArrayList<Object> wrappedError = wrapError(exception);
|
ArrayList<Object> wrappedError = wrapError(exception);
|
||||||
wrapped = wrappedError;
|
wrapped = wrappedError;
|
@ -1,36 +1,24 @@
|
|||||||
package me.polynom.moxplatform_android;
|
package me.polynom.moxplatform_android;
|
||||||
|
|
||||||
import static androidx.core.content.ContextCompat.getSystemService;
|
import static androidx.core.content.ContextCompat.getSystemService;
|
||||||
import static me.polynom.moxplatform_android.ConstantsKt.MARK_AS_READ_ACTION;
|
|
||||||
import static me.polynom.moxplatform_android.ConstantsKt.MARK_AS_READ_ID_KEY;
|
|
||||||
import static me.polynom.moxplatform_android.ConstantsKt.REPLY_TEXT_KEY;
|
|
||||||
import static me.polynom.moxplatform_android.RecordSentMessageKt.recordSentMessage;
|
import static me.polynom.moxplatform_android.RecordSentMessageKt.recordSentMessage;
|
||||||
import static me.polynom.moxplatform_android.CryptoKt.*;
|
import static me.polynom.moxplatform_android.CryptoKt.*;
|
||||||
import me.polynom.moxplatform_android.Notifications.*;
|
import me.polynom.moxplatform_android.Api.*;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.app.RemoteInput;
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
|
||||||
import androidx.core.app.Person;
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -46,7 +34,7 @@ import io.flutter.plugin.common.JSONMethodCodec;
|
|||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
|
|
||||||
public class MoxplatformAndroidPlugin extends BroadcastReceiver implements FlutterPlugin, MethodCallHandler, ServiceAware, NotificationsImplementationApi {
|
public class MoxplatformAndroidPlugin extends BroadcastReceiver implements FlutterPlugin, MethodCallHandler, ServiceAware, MoxplatformApi {
|
||||||
public static final String entrypointKey = "entrypoint_handle";
|
public static final String entrypointKey = "entrypoint_handle";
|
||||||
public static final String extraDataKey = "extra_data";
|
public static final String extraDataKey = "extra_data";
|
||||||
private static final String autoStartAtBootKey = "auto_start_at_boot";
|
private static final String autoStartAtBootKey = "auto_start_at_boot";
|
||||||
@ -60,8 +48,6 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
private MethodChannel channel;
|
private MethodChannel channel;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
private FileProvider provider = new FileProvider();
|
|
||||||
|
|
||||||
public MoxplatformAndroidPlugin() {
|
public MoxplatformAndroidPlugin() {
|
||||||
_instances.add(this);
|
_instances.add(this);
|
||||||
}
|
}
|
||||||
@ -75,7 +61,7 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this.context);
|
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this.context);
|
||||||
localBroadcastManager.registerReceiver(this, new IntentFilter(methodChannelKey));
|
localBroadcastManager.registerReceiver(this, new IntentFilter(methodChannelKey));
|
||||||
|
|
||||||
NotificationsImplementationApi.setup(flutterPluginBinding.getBinaryMessenger(), this);
|
MoxplatformApi.setup(flutterPluginBinding.getBinaryMessenger(), this);
|
||||||
|
|
||||||
Log.d(TAG, "Attached to engine");
|
Log.d(TAG, "Attached to engine");
|
||||||
}
|
}
|
||||||
@ -292,62 +278,18 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showMessagingNotification(@NonNull MessagingNotification notification) {
|
public void showMessagingNotification(@NonNull MessagingNotification notification) {
|
||||||
// Create a reply button
|
NotificationsKt.showMessagingNotification(context, notification);
|
||||||
// TODO: i18n
|
}
|
||||||
RemoteInput remoteInput = new RemoteInput.Builder(REPLY_TEXT_KEY).setLabel("Reply").build();
|
|
||||||
final Intent replyIntent = new Intent(context, NotificationReceiver.class);
|
|
||||||
final PendingIntent replyPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
// TODO: i18n
|
|
||||||
// TODO: Correct icon
|
|
||||||
final NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_service_icon, "Reply", replyPendingIntent)
|
|
||||||
.addRemoteInput(remoteInput)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Create the "mark as read" button
|
@NonNull
|
||||||
final Intent markAsReadIntent = new Intent(context, NotificationReceiver.class);
|
@Override
|
||||||
markAsReadIntent.setAction(MARK_AS_READ_ACTION);
|
public String getPersistentDataPath() {
|
||||||
markAsReadIntent.putExtra(MARK_AS_READ_ID_KEY, notification.getId());
|
return context.getFilesDir().getPath();
|
||||||
// TODO: Replace with something more useful
|
}
|
||||||
markAsReadIntent.putExtra("title", notification.getTitle());
|
|
||||||
final PendingIntent markAsReadPendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, readIntent,PendingIntent.FLAG_CANCEL_CURRENT);
|
|
||||||
|
|
||||||
final NotificationCompat.MessagingStyle style = new NotificationCompat.MessagingStyle("Me")
|
@NonNull
|
||||||
.setConversationTitle(notification.getTitle());
|
@Override
|
||||||
for (final NotificationMessage message : notification.getMessages()) {
|
public String getCacheDataPath() {
|
||||||
// Build the sender of the message
|
return context.getCacheDir().getPath();
|
||||||
final Person.Builder personBuilder = new Person.Builder()
|
|
||||||
.setName(message.getSender())
|
|
||||||
.setKey(message.getJid());
|
|
||||||
if (message.getAvatarPath() != null) {
|
|
||||||
final IconCompat icon = IconCompat.createWithAdaptiveBitmap(
|
|
||||||
BitmapFactory.decodeFile(message.getAvatarPath())
|
|
||||||
);
|
|
||||||
personBuilder.setIcon(icon);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the message
|
|
||||||
final String content = message.getContent().getBody() == null ? "" : message.getContent().getBody();
|
|
||||||
final NotificationCompat.MessagingStyle.Message msg = new NotificationCompat.MessagingStyle.Message(
|
|
||||||
content,
|
|
||||||
message.getTimestamp(),
|
|
||||||
personBuilder.build()
|
|
||||||
);
|
|
||||||
// Turn the image path to a content Uri, if a media file was specified
|
|
||||||
if (message.getContent().getMime() != null && message.getContent().getPath() != null) {
|
|
||||||
final Uri fileUri = androidx.core.content.FileProvider.getUriForFile(context, "me.polynom.moxplatform_android.fileprovider", new File(message.getContent().getPath()));
|
|
||||||
msg.setData(message.getContent().getMime(), fileUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
style.addMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build the notification and send it
|
|
||||||
final NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, notification.getChannelId())
|
|
||||||
.setStyle(style)
|
|
||||||
// TODO: This is wrong
|
|
||||||
.setSmallIcon(R.drawable.ic_service_icon)
|
|
||||||
.addAction(action)
|
|
||||||
.addAction(R.drawable.ic_service_icon, "Mark as read", markAsReadPendingIntent);
|
|
||||||
NotificationManagerCompat.from(context).notify(notification.getId().intValue(), notificationBuilder.build());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
package me.polynom.moxplatform_android
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.app.Person
|
||||||
|
import androidx.core.app.RemoteInput
|
||||||
|
import androidx.core.content.FileProvider
|
||||||
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/// Show a messaging style notification described by @notification.
|
||||||
|
fun showMessagingNotification(context: Context, notification: Api.MessagingNotification) {
|
||||||
|
// Build the actions
|
||||||
|
// -> Reply action
|
||||||
|
val remoteInput = RemoteInput.Builder(REPLY_TEXT_KEY).apply {
|
||||||
|
// TODO: i18n
|
||||||
|
setLabel("Reply")
|
||||||
|
}.build()
|
||||||
|
val replyIntent = Intent(context, NotificationReceiver::class.java)
|
||||||
|
val replyPendingIntent = PendingIntent.getBroadcast(
|
||||||
|
context.applicationContext,
|
||||||
|
0,
|
||||||
|
replyIntent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT,
|
||||||
|
)
|
||||||
|
val replyAction = NotificationCompat.Action.Builder(
|
||||||
|
// TODO: Wrong icon?
|
||||||
|
R.drawable.ic_service_icon,
|
||||||
|
// TODO: i18n
|
||||||
|
"Reply",
|
||||||
|
replyPendingIntent,
|
||||||
|
).apply {
|
||||||
|
addRemoteInput(remoteInput)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
// -> Mark as read action
|
||||||
|
val markAsReadIntent = Intent(context, NotificationReceiver::class.java).apply {
|
||||||
|
action = MARK_AS_READ_ACTION
|
||||||
|
// TODO: Put the JID here
|
||||||
|
putExtra("title", notification.title)
|
||||||
|
}
|
||||||
|
val markAsReadPendingIntent = PendingIntent.getBroadcast(
|
||||||
|
context.applicationContext,
|
||||||
|
0,
|
||||||
|
markAsReadIntent,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Build the notification
|
||||||
|
// TODO: Use a person
|
||||||
|
// TODO: i18n
|
||||||
|
val style = NotificationCompat.MessagingStyle("Me");
|
||||||
|
for (message in notification.messages) {
|
||||||
|
// Build the sender
|
||||||
|
val sender = Person.Builder().apply {
|
||||||
|
setName(message.sender)
|
||||||
|
setKey(message.jid)
|
||||||
|
|
||||||
|
// Set the avatar, if available
|
||||||
|
if (message.avatarPath != null) {
|
||||||
|
setIcon(
|
||||||
|
IconCompat.createWithAdaptiveBitmap(
|
||||||
|
BitmapFactory.decodeFile(message.avatarPath),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
// Build the message
|
||||||
|
val body = message.content.body ?: ""
|
||||||
|
val msg = NotificationCompat.MessagingStyle.Message(
|
||||||
|
body,
|
||||||
|
message.timestamp,
|
||||||
|
sender,
|
||||||
|
)
|
||||||
|
// If we got an image, turn it into a content URI and set it
|
||||||
|
if (message.content.mime != null && message.content.path != null) {
|
||||||
|
val fileUri = FileProvider.getUriForFile(
|
||||||
|
context,
|
||||||
|
"me.polynom.moxplatform_android.fileprovider",
|
||||||
|
File(message.content.path),
|
||||||
|
)
|
||||||
|
msg.setData(message.content.mime, fileUri)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the message
|
||||||
|
style.addMessage(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assemble the notification
|
||||||
|
val finalNotification = NotificationCompat.Builder(context, notification.channelId).apply {
|
||||||
|
setStyle(style)
|
||||||
|
// TODO: I think this is wrong
|
||||||
|
setSmallIcon(R.drawable.ic_service_icon)
|
||||||
|
|
||||||
|
addAction(replyAction)
|
||||||
|
addAction(
|
||||||
|
// TODO: Wrong icon
|
||||||
|
R.drawable.ic_service_icon,
|
||||||
|
// TODO: i18n
|
||||||
|
"Mark as read",
|
||||||
|
markAsReadPendingIntent,
|
||||||
|
)
|
||||||
|
}.build()
|
||||||
|
|
||||||
|
// Post the notification
|
||||||
|
NotificationManagerCompat.from(context).notify(
|
||||||
|
notification.id.toInt(),
|
||||||
|
finalNotification,
|
||||||
|
)
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<!-- For testing -->
|
<!-- For testing -->
|
||||||
<cache-path name="file_picker" path="file_picker/"/>
|
<cache-path name="file_picker" path="file_picker/"/>
|
||||||
|
|
||||||
|
<!-- Moxxy -->
|
||||||
|
<files-path name="media" path="media/" />
|
||||||
</paths>
|
</paths>
|
@ -1,6 +1,5 @@
|
|||||||
library moxplatform_android;
|
library moxplatform_android;
|
||||||
|
|
||||||
export 'src/isolate_android.dart';
|
export 'src/isolate_android.dart';
|
||||||
export 'src/media_android.dart';
|
|
||||||
export 'src/plugin_android.dart';
|
export 'src/plugin_android.dart';
|
||||||
export 'src/service_android.dart';
|
export 'src/service_android.dart';
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import 'package:media_scanner/media_scanner.dart';
|
|
||||||
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
|
||||||
|
|
||||||
class AndroidMediaScannerImplementation extends MediaScannerImplementation {
|
|
||||||
@override
|
|
||||||
void scanFile(String path) {
|
|
||||||
MediaScanner.loadMedia(path: path);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
||||||
|
|
||||||
class AndroidNotificationsImplementation extends NotificationsImplementation {
|
class AndroidNotificationsImplementation extends NotificationsImplementation {
|
||||||
final NotificationsImplementationApi _api = NotificationsImplementationApi();
|
final MoxplatformApi _api = MoxplatformApi();
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
13
packages/moxplatform_android/lib/src/platform_android.dart
Normal file
13
packages/moxplatform_android/lib/src/platform_android.dart
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
||||||
|
|
||||||
|
class AndroidPlatformImplementation extends PlatformImplementation {
|
||||||
|
@override
|
||||||
|
Future<String> getCacheDataPath() {
|
||||||
|
return MoxplatformInterface.api.getCacheDataPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String> getPersistentDataPath() {
|
||||||
|
return MoxplatformInterface.api.getPersistentDataPath();
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,8 @@
|
|||||||
import 'package:moxplatform_android/src/contacts_android.dart';
|
import 'package:moxplatform_android/src/contacts_android.dart';
|
||||||
import 'package:moxplatform_android/src/crypto_android.dart';
|
import 'package:moxplatform_android/src/crypto_android.dart';
|
||||||
import 'package:moxplatform_android/src/isolate_android.dart';
|
import 'package:moxplatform_android/src/isolate_android.dart';
|
||||||
import 'package:moxplatform_android/src/media_android.dart';
|
|
||||||
import 'package:moxplatform_android/src/notifications_android.dart';
|
import 'package:moxplatform_android/src/notifications_android.dart';
|
||||||
|
import 'package:moxplatform_android/src/platform_android.dart';
|
||||||
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
import 'package:moxplatform_platform_interface/moxplatform_platform_interface.dart';
|
||||||
|
|
||||||
class MoxplatformAndroidPlugin extends MoxplatformInterface {
|
class MoxplatformAndroidPlugin extends MoxplatformInterface {
|
||||||
@ -12,8 +12,8 @@ class MoxplatformAndroidPlugin extends MoxplatformInterface {
|
|||||||
MoxplatformInterface.contacts = AndroidContactsImplementation();
|
MoxplatformInterface.contacts = AndroidContactsImplementation();
|
||||||
MoxplatformInterface.crypto = AndroidCryptographyImplementation();
|
MoxplatformInterface.crypto = AndroidCryptographyImplementation();
|
||||||
MoxplatformInterface.handler = AndroidIsolateHandler();
|
MoxplatformInterface.handler = AndroidIsolateHandler();
|
||||||
MoxplatformInterface.media = AndroidMediaScannerImplementation();
|
|
||||||
MoxplatformInterface.notifications = AndroidNotificationsImplementation();
|
MoxplatformInterface.notifications = AndroidNotificationsImplementation();
|
||||||
|
MoxplatformInterface.platform = AndroidPlatformImplementation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -22,7 +22,6 @@ dependencies:
|
|||||||
sdk: flutter
|
sdk: flutter
|
||||||
get_it: ^7.2.0
|
get_it: ^7.2.0
|
||||||
logging: ^1.0.2
|
logging: ^1.0.2
|
||||||
media_scanner: ^2.0.0
|
|
||||||
meta: ^1.7.0
|
meta: ^1.7.0
|
||||||
moxlib:
|
moxlib:
|
||||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
library moxplatform_platform_interface;
|
library moxplatform_platform_interface;
|
||||||
|
|
||||||
|
export 'src/api.g.dart';
|
||||||
export 'src/contacts.dart';
|
export 'src/contacts.dart';
|
||||||
export 'src/contacts_stub.dart';
|
export 'src/contacts_stub.dart';
|
||||||
export 'src/crypto.dart';
|
export 'src/crypto.dart';
|
||||||
@ -7,9 +8,8 @@ export 'src/crypto_stub.dart';
|
|||||||
export 'src/interface.dart';
|
export 'src/interface.dart';
|
||||||
export 'src/isolate.dart';
|
export 'src/isolate.dart';
|
||||||
export 'src/isolate_stub.dart';
|
export 'src/isolate_stub.dart';
|
||||||
export 'src/media.dart';
|
|
||||||
export 'src/media_stub.dart';
|
|
||||||
export 'src/notifications.dart';
|
export 'src/notifications.dart';
|
||||||
export 'src/notifications.g.dart';
|
|
||||||
export 'src/notifications_stub.dart';
|
export 'src/notifications_stub.dart';
|
||||||
|
export 'src/platform.dart';
|
||||||
|
export 'src/platform_stub.dart';
|
||||||
export 'src/service.dart';
|
export 'src/service.dart';
|
||||||
|
@ -127,8 +127,8 @@ class MessagingNotification {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _NotificationsImplementationApiCodec extends StandardMessageCodec {
|
class _MoxplatformApiCodec extends StandardMessageCodec {
|
||||||
const _NotificationsImplementationApiCodec();
|
const _MoxplatformApiCodec();
|
||||||
@override
|
@override
|
||||||
void writeValue(WriteBuffer buffer, Object? value) {
|
void writeValue(WriteBuffer buffer, Object? value) {
|
||||||
if (value is MessagingNotification) {
|
if (value is MessagingNotification) {
|
||||||
@ -160,19 +160,19 @@ class _NotificationsImplementationApiCodec extends StandardMessageCodec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotificationsImplementationApi {
|
class MoxplatformApi {
|
||||||
/// Constructor for [NotificationsImplementationApi]. The [binaryMessenger] named argument is
|
/// Constructor for [MoxplatformApi]. The [binaryMessenger] named argument is
|
||||||
/// available for dependency injection. If it is left null, the default
|
/// available for dependency injection. If it is left null, the default
|
||||||
/// BinaryMessenger will be used which routes to the host platform.
|
/// BinaryMessenger will be used which routes to the host platform.
|
||||||
NotificationsImplementationApi({BinaryMessenger? binaryMessenger})
|
MoxplatformApi({BinaryMessenger? binaryMessenger})
|
||||||
: _binaryMessenger = binaryMessenger;
|
: _binaryMessenger = binaryMessenger;
|
||||||
final BinaryMessenger? _binaryMessenger;
|
final BinaryMessenger? _binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> codec = _NotificationsImplementationApiCodec();
|
static const MessageCodec<Object?> codec = _MoxplatformApiCodec();
|
||||||
|
|
||||||
Future<void> createNotificationChannel(String arg_title, String arg_id, bool arg_urgent) async {
|
Future<void> createNotificationChannel(String arg_title, String arg_id, bool arg_urgent) async {
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.NotificationsImplementationApi.createNotificationChannel', codec,
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.createNotificationChannel', codec,
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList =
|
final List<Object?>? replyList =
|
||||||
await channel.send(<Object?>[arg_title, arg_id, arg_urgent]) as List<Object?>?;
|
await channel.send(<Object?>[arg_title, arg_id, arg_urgent]) as List<Object?>?;
|
||||||
@ -194,7 +194,7 @@ class NotificationsImplementationApi {
|
|||||||
|
|
||||||
Future<void> showMessagingNotification(MessagingNotification arg_notification) async {
|
Future<void> showMessagingNotification(MessagingNotification arg_notification) async {
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.moxplatform_platform_interface.NotificationsImplementationApi.showMessagingNotification', codec,
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.showMessagingNotification', codec,
|
||||||
binaryMessenger: _binaryMessenger);
|
binaryMessenger: _binaryMessenger);
|
||||||
final List<Object?>? replyList =
|
final List<Object?>? replyList =
|
||||||
await channel.send(<Object?>[arg_notification]) as List<Object?>?;
|
await channel.send(<Object?>[arg_notification]) as List<Object?>?;
|
||||||
@ -213,4 +213,58 @@ class NotificationsImplementationApi {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String> getPersistentDataPath() async {
|
||||||
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getPersistentDataPath', codec,
|
||||||
|
binaryMessenger: _binaryMessenger);
|
||||||
|
final List<Object?>? replyList =
|
||||||
|
await channel.send(null) as List<Object?>?;
|
||||||
|
if (replyList == null) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: 'channel-error',
|
||||||
|
message: 'Unable to establish connection on channel.',
|
||||||
|
);
|
||||||
|
} else if (replyList.length > 1) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: replyList[0]! as String,
|
||||||
|
message: replyList[1] as String?,
|
||||||
|
details: replyList[2],
|
||||||
|
);
|
||||||
|
} else if (replyList[0] == null) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: 'null-error',
|
||||||
|
message: 'Host platform returned null value for non-null return value.',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (replyList[0] as String?)!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> getCacheDataPath() async {
|
||||||
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
|
'dev.flutter.pigeon.moxplatform_platform_interface.MoxplatformApi.getCacheDataPath', codec,
|
||||||
|
binaryMessenger: _binaryMessenger);
|
||||||
|
final List<Object?>? replyList =
|
||||||
|
await channel.send(null) as List<Object?>?;
|
||||||
|
if (replyList == null) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: 'channel-error',
|
||||||
|
message: 'Unable to establish connection on channel.',
|
||||||
|
);
|
||||||
|
} else if (replyList.length > 1) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: replyList[0]! as String,
|
||||||
|
message: replyList[1] as String?,
|
||||||
|
details: replyList[2],
|
||||||
|
);
|
||||||
|
} else if (replyList[0] == null) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: 'null-error',
|
||||||
|
message: 'Host platform returned null value for non-null return value.',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (replyList[0] as String?)!;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,13 +1,14 @@
|
|||||||
|
import 'package:moxplatform_platform_interface/src/api.g.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/contacts.dart';
|
import 'package:moxplatform_platform_interface/src/contacts.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/contacts_stub.dart';
|
import 'package:moxplatform_platform_interface/src/contacts_stub.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/crypto.dart';
|
import 'package:moxplatform_platform_interface/src/crypto.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/crypto_stub.dart';
|
import 'package:moxplatform_platform_interface/src/crypto_stub.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/isolate.dart';
|
import 'package:moxplatform_platform_interface/src/isolate.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/isolate_stub.dart';
|
import 'package:moxplatform_platform_interface/src/isolate_stub.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/media.dart';
|
|
||||||
import 'package:moxplatform_platform_interface/src/media_stub.dart';
|
|
||||||
import 'package:moxplatform_platform_interface/src/notifications.dart';
|
import 'package:moxplatform_platform_interface/src/notifications.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/notifications_stub.dart';
|
import 'package:moxplatform_platform_interface/src/notifications_stub.dart';
|
||||||
|
import 'package:moxplatform_platform_interface/src/platform.dart';
|
||||||
|
import 'package:moxplatform_platform_interface/src/platform_stub.dart';
|
||||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||||
|
|
||||||
abstract class MoxplatformInterface extends PlatformInterface {
|
abstract class MoxplatformInterface extends PlatformInterface {
|
||||||
@ -15,11 +16,13 @@ abstract class MoxplatformInterface extends PlatformInterface {
|
|||||||
|
|
||||||
static final Object _token = Object();
|
static final Object _token = Object();
|
||||||
|
|
||||||
|
static MoxplatformApi api = MoxplatformApi();
|
||||||
|
|
||||||
static IsolateHandler handler = StubIsolateHandler();
|
static IsolateHandler handler = StubIsolateHandler();
|
||||||
static MediaScannerImplementation media = StubMediaScannerImplementation();
|
|
||||||
static CryptographyImplementation crypto = StubCryptographyImplementation();
|
static CryptographyImplementation crypto = StubCryptographyImplementation();
|
||||||
static ContactsImplementation contacts = StubContactsImplementation();
|
static ContactsImplementation contacts = StubContactsImplementation();
|
||||||
static NotificationsImplementation notifications = StubNotificationsImplementation();
|
static NotificationsImplementation notifications = StubNotificationsImplementation();
|
||||||
|
static PlatformImplementation platform = StubPlatformImplementation();
|
||||||
|
|
||||||
/// Return the current platform name.
|
/// Return the current platform name.
|
||||||
Future<String?> getPlatformName();
|
Future<String?> getPlatformName();
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
/// Wrapper around platform-specific media scanning
|
|
||||||
// ignore: one_member_abstracts
|
|
||||||
abstract class MediaScannerImplementation {
|
|
||||||
/// Let the platform-specific media scanner scan the file at [path].
|
|
||||||
void scanFile(String path);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
import 'package:moxplatform_platform_interface/src/media.dart';
|
|
||||||
|
|
||||||
class StubMediaScannerImplementation extends MediaScannerImplementation {
|
|
||||||
@override
|
|
||||||
void scanFile(String path) {}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:moxplatform_platform_interface/src/notifications.g.dart';
|
import 'package:moxplatform_platform_interface/src/api.g.dart';
|
||||||
|
|
||||||
abstract class NotificationsImplementation {
|
abstract class NotificationsImplementation {
|
||||||
Future<void> createNotificationChannel(String title, String id, bool urgent);
|
Future<void> createNotificationChannel(String title, String id, bool urgent);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:moxplatform_platform_interface/src/notifications.g.dart';
|
import 'package:moxplatform_platform_interface/src/api.g.dart';
|
||||||
import 'package:moxplatform_platform_interface/src/notifications.dart';
|
import 'package:moxplatform_platform_interface/src/notifications.dart';
|
||||||
|
|
||||||
class StubNotificationsImplementation extends NotificationsImplementation {
|
class StubNotificationsImplementation extends NotificationsImplementation {
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
abstract class PlatformImplementation {
|
||||||
|
/// Returns the path where persistent data should be stored.
|
||||||
|
Future<String> getPersistentDataPath();
|
||||||
|
|
||||||
|
/// Returns the path where cache data should be stored.
|
||||||
|
Future<String> getCacheDataPath();
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
import 'package:moxplatform_platform_interface/src/platform.dart';
|
||||||
|
|
||||||
|
class StubPlatformImplementation extends PlatformImplementation {
|
||||||
|
/// Returns the path where persistent data should be stored.
|
||||||
|
Future<String> getPersistentDataPath() async => "";
|
||||||
|
|
||||||
|
/// Returns the path where cache data should be stored.
|
||||||
|
Future<String> getCacheDataPath() async => "";
|
||||||
|
}
|
@ -2,12 +2,12 @@ import 'package:pigeon/pigeon.dart';
|
|||||||
|
|
||||||
@ConfigurePigeon(
|
@ConfigurePigeon(
|
||||||
PigeonOptions(
|
PigeonOptions(
|
||||||
dartOut: 'packages/moxplatform_platform_interface/lib/src/notifications.g.dart',
|
dartOut: 'packages/moxplatform_platform_interface/lib/src/api.g.dart',
|
||||||
//kotlinOut: 'packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Notifications.g.kt',
|
//kotlinOut: 'packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Notifications.g.kt',
|
||||||
//kotlinOptions: KotlinOptions(
|
//kotlinOptions: KotlinOptions(
|
||||||
// package: 'me.polynom.moxplatform_android',
|
// package: 'me.polynom.moxplatform_android',
|
||||||
//),
|
//),
|
||||||
javaOut: 'packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Notifications.java',
|
javaOut: 'packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/Api.java',
|
||||||
javaOptions: JavaOptions(
|
javaOptions: JavaOptions(
|
||||||
package: 'me.polynom.moxplatform_android',
|
package: 'me.polynom.moxplatform_android',
|
||||||
),
|
),
|
||||||
@ -70,8 +70,12 @@ class MessagingNotification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@HostApi()
|
@HostApi()
|
||||||
abstract class NotificationsImplementationApi {
|
abstract class MoxplatformApi {
|
||||||
void createNotificationChannel(String title, String id, bool urgent);
|
void createNotificationChannel(String title, String id, bool urgent);
|
||||||
|
|
||||||
void showMessagingNotification(MessagingNotification notification);
|
void showMessagingNotification(MessagingNotification notification);
|
||||||
|
|
||||||
|
String getPersistentDataPath();
|
||||||
|
|
||||||
|
String getCacheDataPath();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user