diff --git a/packages/moxplatform_android/android/build.gradle b/packages/moxplatform_android/android/build.gradle index 5bf9414..89b86f2 100644 --- a/packages/moxplatform_android/android/build.gradle +++ b/packages/moxplatform_android/android/build.gradle @@ -2,13 +2,17 @@ group 'me.polynom.moxplatform_android' version '1.0' buildscript { + ext { + kotlin_version = '1.8.21' + } repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.1.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -20,6 +24,7 @@ rootProject.allprojects { } apply plugin: 'com.android.library' +apply plugin: 'org.jetbrains.kotlin.android' android { compileSdkVersion 31 diff --git a/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java index 5e8e1e3..0a17b82 100644 --- a/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java +++ b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/MoxplatformAndroidPlugin.java @@ -1,5 +1,7 @@ package me.polynom.moxplatform_android; +import static me.polynom.moxplatform_android.RecordSentMessageKt.recordSentMessage; + import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; @@ -204,17 +206,13 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt break; case "recordSentMessage": ArrayList rargs = (ArrayList) call.arguments; - try { - recordSentMessage( - (String) rargs.get(0), - (String) rargs.get(1), - (String) rargs.get(2), - (int) rargs.get(3) - ); - } catch (ClassNotFoundException ex) { - Log.e(TAG, "Failed to get classname"); - Log.e(TAG, ex.getMessage()); - } + recordSentMessage( + context, + (String) rargs.get(0), + (String) rargs.get(1), + (String) rargs.get(2), + (int) rargs.get(3) + ); result.success(true); break; default: @@ -223,58 +221,6 @@ public class MoxplatformAndroidPlugin extends BroadcastReceiver implements Flutt } } - private void recordSentMessage(String name, String jid, String avatarPath, int fallbackIconType) throws ClassNotFoundException { - // Very much inspired (or copied) from https://github.com/ShoutSocial/share_handler - final String pkgName = context.getPackageName(); - final Intent intent = new Intent(context, Class.forName(pkgName + ".MainActivity")); - intent.setAction(Intent.ACTION_SEND); - - // Compatibility with share_handler - intent.putExtra("conversationIdentifier", jid); - - final String shortcutTarget = pkgName + ".dynamic_share_target"; - final ShortcutInfoCompat.Builder builder = new ShortcutInfoCompat.Builder(context, name); - builder - .setShortLabel(name) - .setIsConversation() - .setCategories(Set.of(shortcutTarget)) - .setIntent(intent) - .setLongLived(true); - - // TODO: This is dumb. Maybe just raise the minimum Android version - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { - final Person.Builder personBuilder = new Person.Builder() - .setKey(jid) - .setName(name); - - if (avatarPath != null) { - final Bitmap bitmap = BitmapFactory.decodeFile(avatarPath); - final IconCompat icon = IconCompat.createWithAdaptiveBitmap(bitmap); - builder.setIcon(icon); - personBuilder.setIcon(icon); - } else { - if (fallbackIconType == 0 || fallbackIconType == 1) { - final int id = switch (fallbackIconType) { - default: - case 0: yield R.mipmap.person; - case 1: yield R.mipmap.notes; - }; - final IconCompat personIcon = IconCompat.createWithResource( - context, - id - ); - builder.setIcon(personIcon); - personBuilder.setIcon(personIcon); - } - } - - builder.setPerson(personBuilder.build()); - } - - final ShortcutInfoCompat shortcut = builder.build(); - ShortcutManagerCompat.addDynamicShortcuts(context, List.of(shortcut)); - } - @Override public void onReceive(Context context, Intent intent) { if (intent.getAction() == null) return; diff --git a/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/RecordSentMessage.kt b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/RecordSentMessage.kt new file mode 100644 index 0000000..238b932 --- /dev/null +++ b/packages/moxplatform_android/android/src/main/java/me/polynom/moxplatform_android/RecordSentMessage.kt @@ -0,0 +1,62 @@ +package me.polynom.moxplatform_android + +import android.content.Context +import android.content.Intent +import android.graphics.BitmapFactory +import androidx.core.app.Person +import androidx.core.content.pm.ShortcutInfoCompat +import androidx.core.content.pm.ShortcutManagerCompat +import androidx.core.graphics.drawable.IconCompat + +/* + * Uses Android's direct share API to create dynamic share targets that are compatible + * with share_handler's media handling. + * */ +fun recordSentMessage(context: Context, name: String, jid: String, avatarPath: String?, fallbackIconType: Int) { + val pkgName = context.packageName + val intent = Intent(context, Class.forName("$pkgName.MainActivity")).apply { + action = Intent.ACTION_SEND + + // Compatibility with share_handler + putExtra("conversationIdentifier", jid) + } + + val shortcutTarget = "$pkgName.dynamic_share_target" + val shortcutBuilder = ShortcutInfoCompat.Builder(context, name).apply { + setShortLabel(name) + setIsConversation() + setCategories(setOf(shortcutTarget)) + setIntent(intent) + setLongLived(true) + } + + val personBuilder = Person.Builder().apply { + setKey(jid) + setName(name) + } + + // Either set an avatar image OR a fallback icon + if (avatarPath != null) { + val icon = IconCompat.createWithAdaptiveBitmap( + BitmapFactory.decodeFile(avatarPath), + ) + shortcutBuilder.setIcon(icon) + personBuilder.setIcon(icon) + } else { + val resourceId = when(fallbackIconType) { + 0 -> R.mipmap.person + 1 -> R.mipmap.notes + // "Fallthrough" + else -> R.mipmap.person + } + val icon = IconCompat.createWithResource(context, resourceId) + shortcutBuilder.setIcon(icon) + personBuilder.setIcon(icon) + } + + shortcutBuilder.setPerson(personBuilder.build()) + ShortcutManagerCompat.addDynamicShortcuts( + context, + listOf(shortcutBuilder.build()), + ) +} \ No newline at end of file