mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-21 09:50:13 +08:00
@@ -0,0 +1,84 @@
|
||||
package com.example.piliplus;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
|
||||
import com.github.dart_lang.jni_flutter.JniFlutterPlugin;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@Keep
|
||||
public final class AndroidHelper {
|
||||
private AndroidHelper() {
|
||||
}
|
||||
|
||||
private static Context getContext() {
|
||||
return JniFlutterPlugin.getApplicationContext();
|
||||
}
|
||||
|
||||
public static void back() {
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.addCategory(Intent.CATEGORY_HOME);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
getContext().startActivity(intent);
|
||||
}
|
||||
|
||||
public static int sdkInt() {
|
||||
return Build.VERSION.SDK_INT;
|
||||
}
|
||||
|
||||
public static void openLinkVerifySettings() {
|
||||
Context context = getContext();
|
||||
Uri uri = Uri.parse("package:" + context.getPackageName());
|
||||
try {
|
||||
Intent intent;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
intent = new Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS, uri);
|
||||
} else {
|
||||
intent = new Intent(Intent.ACTION_MAIN, uri);
|
||||
intent.setClassName(
|
||||
"com.android.settings",
|
||||
"com.android.settings.applications.InstalledAppOpenByDefaultActivity"
|
||||
);
|
||||
}
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
} catch (Throwable ignored) {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public static void createShortcut(@NotNull String id, @NotNull String uri, @NotNull String label, @NotNull String icon) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
Context context = getContext();
|
||||
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
|
||||
if (shortcutManager != null && shortcutManager.isRequestPinShortcutSupported()) {
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(icon);
|
||||
ShortcutInfo shortcut = new ShortcutInfo.Builder(context, id)
|
||||
.setShortLabel(label)
|
||||
.setIcon(Icon.createWithAdaptiveBitmap(bitmap))
|
||||
.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(uri)))
|
||||
.build();
|
||||
// TODO: WorkerThread
|
||||
Intent pinIntent = shortcutManager.createShortcutResultIntent(shortcut);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(
|
||||
context, 0, pinIntent, PendingIntent.FLAG_IMMUTABLE
|
||||
);
|
||||
shortcutManager.requestPinShortcut(shortcut, pendingIntent.getIntentSender());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,15 @@
|
||||
package com.example.piliplus
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.app.SearchManager
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.drawable.Icon
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import android.provider.Settings
|
||||
import androidx.core.net.toUri
|
||||
import android.os.Bundle
|
||||
import android.view.WindowManager.LayoutParams
|
||||
import com.ryanheise.audioservice.AudioServiceActivity
|
||||
import io.flutter.SystemChrome
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.SystemChrome
|
||||
|
||||
class MainActivity : AudioServiceActivity() {
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
@@ -25,115 +18,15 @@ class MainActivity : AudioServiceActivity() {
|
||||
val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "PiliPlus")
|
||||
methodChannel.setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"back" -> back()
|
||||
|
||||
"linkVerifySettings" -> {
|
||||
val uri = ("package:" + context.packageName).toUri()
|
||||
try {
|
||||
val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS, uri)
|
||||
} else {
|
||||
Intent("android.intent.action.MAIN", uri).setClassName(
|
||||
"com.android.settings",
|
||||
"com.android.settings.applications.InstalledAppOpenByDefaultActivity"
|
||||
)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
} catch (_: Throwable) {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
||||
"music" -> {
|
||||
val title = call.argument<String>("title")
|
||||
val intent = Intent(MediaStore.INTENT_ACTION_MEDIA_SEARCH).apply {
|
||||
putExtra(SearchManager.QUERY, title)
|
||||
putExtra(MediaStore.EXTRA_MEDIA_TITLE, title)
|
||||
call.argument<String?>("artist")
|
||||
?.let { putExtra(MediaStore.EXTRA_MEDIA_ARTIST, it) }
|
||||
call.argument<String?>("album")
|
||||
?.let { putExtra(MediaStore.EXTRA_MEDIA_ALBUM, it) }
|
||||
|
||||
addCategory(Intent.CATEGORY_DEFAULT)
|
||||
}
|
||||
try {
|
||||
if (packageManager.resolveActivity(
|
||||
intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY
|
||||
) != null
|
||||
) {
|
||||
startActivity(intent)
|
||||
result.success(true)
|
||||
return@setMethodCallHandler
|
||||
}
|
||||
} catch (_: Throwable) {
|
||||
}
|
||||
try {
|
||||
intent.action = MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
|
||||
if (packageManager.resolveActivity(
|
||||
intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY
|
||||
) != null
|
||||
) {
|
||||
startActivity(intent)
|
||||
result.success(true)
|
||||
return@setMethodCallHandler
|
||||
}
|
||||
} catch (_: Throwable) {
|
||||
}
|
||||
result.success(false)
|
||||
}
|
||||
|
||||
"createShortcut" -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
try {
|
||||
val shortcutManager =
|
||||
context.getSystemService(ShortcutManager::class.java)
|
||||
if (shortcutManager.isRequestPinShortcutSupported) {
|
||||
val id = call.argument<String>("id")!!
|
||||
val uri = call.argument<String>("uri")!!
|
||||
val label = call.argument<String>("label")!!
|
||||
val icon = call.argument<String>("icon")!!
|
||||
val bitmap = BitmapFactory.decodeFile(icon)
|
||||
val shortcut =
|
||||
ShortcutInfo.Builder(context, id)
|
||||
.setShortLabel(label)
|
||||
.setIcon(Icon.createWithAdaptiveBitmap(bitmap))
|
||||
.setIntent(Intent(Intent.ACTION_VIEW, uri.toUri()))
|
||||
.build()
|
||||
val pinIntent =
|
||||
shortcutManager.createShortcutResultIntent(shortcut)
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
context, 0, pinIntent, PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
shortcutManager.requestPinShortcut(
|
||||
shortcut,
|
||||
pendingIntent.intentSender
|
||||
)
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"sdkInt" -> {
|
||||
result.success(Build.VERSION.SDK_INT)
|
||||
}
|
||||
|
||||
"SystemChrome.setEnabledSystemUIMode" -> {
|
||||
SystemChrome.onMethodCall(
|
||||
this,
|
||||
"SystemChrome.setEnabledSystemUIMode",
|
||||
call.argument("arguments")
|
||||
this, "SystemChrome.setEnabledSystemUIMode", call.argument("arguments")
|
||||
)
|
||||
}
|
||||
|
||||
"SystemChrome.setEnabledSystemUIOverlays" -> {
|
||||
SystemChrome.onMethodCall(
|
||||
this,
|
||||
"SystemChrome.setEnabledSystemUIOverlays",
|
||||
call.argument("arguments")
|
||||
this, "SystemChrome.setEnabledSystemUIOverlays", call.argument("arguments")
|
||||
)
|
||||
}
|
||||
|
||||
@@ -142,12 +35,12 @@ class MainActivity : AudioServiceActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun back() {
|
||||
val intent = Intent(Intent.ACTION_MAIN).apply {
|
||||
addCategory(Intent.CATEGORY_HOME)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
window.attributes.layoutInDisplayCutoutMode =
|
||||
LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@@ -156,13 +49,11 @@ class MainActivity : AudioServiceActivity() {
|
||||
}
|
||||
|
||||
override fun onPictureInPictureModeChanged(
|
||||
isInPictureInPictureMode: Boolean,
|
||||
newConfig: Configuration?
|
||||
isInPictureInPictureMode: Boolean, newConfig: Configuration?
|
||||
) {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
||||
MethodChannel(
|
||||
flutterEngine!!.dartExecutor.binaryMessenger,
|
||||
"floating"
|
||||
).invokeMethod("onPipChanged", isInPictureInPictureMode)
|
||||
MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, "floating").invokeMethod(
|
||||
"onPipChanged", isInPictureInPictureMode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -18,7 +18,6 @@ import 'package:PiliPlus/services/service_locator.dart';
|
||||
import 'package:PiliPlus/utils/cache_manager.dart';
|
||||
import 'package:PiliPlus/utils/calc_window_position.dart';
|
||||
import 'package:PiliPlus/utils/date_utils.dart';
|
||||
import 'package:PiliPlus/utils/device_utils.dart';
|
||||
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
||||
import 'package:PiliPlus/utils/json_file_handler.dart';
|
||||
import 'package:PiliPlus/utils/path_utils.dart';
|
||||
@@ -84,10 +83,6 @@ Future<void> _initAppPath() async {
|
||||
appSupportDirPath = (await getApplicationSupportDirectory()).path;
|
||||
}
|
||||
|
||||
Future<void> _initSdkInt() async {
|
||||
DeviceUtils.sdkInt = await Utils.channel.invokeMethod('sdkInt');
|
||||
}
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
MediaKit.ensureInitialized();
|
||||
@@ -109,7 +104,6 @@ void main() async {
|
||||
|
||||
if (PlatformUtils.isMobile) {
|
||||
await Future.wait([
|
||||
if (Platform.isAndroid) _initSdkInt(),
|
||||
if (Pref.horizontalScreen) ?fullMode() else ?portraitUpMode(),
|
||||
setupServiceLocator(),
|
||||
]);
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:PiliPlus/pages/mine/controller.dart';
|
||||
import 'package:PiliPlus/services/logger.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
import 'package:PiliPlus/utils/accounts/account.dart';
|
||||
import 'package:PiliPlus/utils/android/bindings.g.dart';
|
||||
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||
import 'package:PiliPlus/utils/cache_manager.dart';
|
||||
import 'package:PiliPlus/utils/date_utils.dart';
|
||||
@@ -179,7 +180,7 @@ Commit Hash: ${BuildConfig.commitHash}''',
|
||||
),
|
||||
if (Platform.isAndroid)
|
||||
ListTile(
|
||||
onTap: () => Utils.channel.invokeMethod('linkVerifySettings'),
|
||||
onTap: AndroidHelper.openLinkVerifySettings,
|
||||
leading: const Icon(MdiIcons.linkBoxOutline),
|
||||
title: const Text('打开受支持的链接'),
|
||||
trailing: Icon(
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:PiliPlus/models/common/nav_bar_config.dart';
|
||||
import 'package:PiliPlus/pages/home/view.dart';
|
||||
import 'package:PiliPlus/pages/main/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/utils/android/bindings.g.dart';
|
||||
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||
import 'package:PiliPlus/utils/extension/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/size_ext.dart';
|
||||
@@ -18,7 +19,6 @@ import 'package:PiliPlus/utils/mobile_observer.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
@@ -202,9 +202,10 @@ class _MainAppState extends PopScopeState<MainApp>
|
||||
await trayManager.setContextMenu(trayMenu);
|
||||
}
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
static void _onBack() {
|
||||
if (Platform.isAndroid) {
|
||||
Utils.channel.invokeMethod('back');
|
||||
AndroidHelper.back();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import 'package:PiliPlus/pages/member_shop/view.dart';
|
||||
import 'package:PiliPlus/pages/member_video_web/archive/view.dart';
|
||||
import 'package:PiliPlus/pages/member_video_web/season_series/view.dart';
|
||||
import 'package:PiliPlus/pages/webview/view.dart';
|
||||
import 'package:PiliPlus/utils/android/android_helper.dart';
|
||||
import 'package:PiliPlus/utils/date_utils.dart';
|
||||
import 'package:PiliPlus/utils/extension/context_ext.dart';
|
||||
import 'package:PiliPlus/utils/extension/string_ext.dart';
|
||||
@@ -704,14 +705,11 @@ class _MemberPageState extends State<MemberPage> {
|
||||
'${_userController.userAvatar!}@200w_200h.webp'.http2https,
|
||||
));
|
||||
SmartDialog.dismiss();
|
||||
await Utils.channel.invokeMethod(
|
||||
'createShortcut',
|
||||
<String, String>{
|
||||
'id': _userController.mid.toString(),
|
||||
'uri': 'bilibili://space/${_userController.mid}',
|
||||
'label': _userController.username!,
|
||||
'icon': file.path,
|
||||
},
|
||||
PiliAndroidHelper.createShortcut(
|
||||
_userController.mid.toString(),
|
||||
'bilibili://space/${_userController.mid}',
|
||||
_userController.username!,
|
||||
file.path,
|
||||
);
|
||||
} catch (e) {
|
||||
SmartDialog.showToast(e.toString());
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:io' show Platform;
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:PiliPlus/common/widgets/badge.dart';
|
||||
@@ -428,15 +427,10 @@ class _MusicDetailPageState extends CommonDynPageState<MusicDetailPage> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => _searchMusic(item),
|
||||
onLongPress: () => Utils.copyText(item.musicTitle!),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: MarqueeText(
|
||||
item.musicTitle!,
|
||||
spacing: 30,
|
||||
style: textTheme.titleMedium,
|
||||
),
|
||||
MarqueeText(
|
||||
item.musicTitle!,
|
||||
spacing: 30,
|
||||
style: textTheme.titleMedium,
|
||||
),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
@@ -558,18 +552,4 @@ class _MusicDetailPageState extends CommonDynPageState<MusicDetailPage> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _searchMusic(MusicDetail item) async {
|
||||
final res =
|
||||
Platform.isAndroid &&
|
||||
(await Utils.channel.invokeMethod<bool>('music', {
|
||||
'title': item.musicTitle,
|
||||
'artist': item.originArtist ?? item.originArtistList,
|
||||
'album': item.album,
|
||||
}) ??
|
||||
false);
|
||||
if (!res) {
|
||||
Utils.copyText(item.musicTitle!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
lib/utils/android/android_helper.dart
Normal file
19
lib/utils/android/android_helper.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
import 'package:PiliPlus/utils/android/bindings.g.dart';
|
||||
import 'package:jni/jni.dart';
|
||||
|
||||
abstract final class PiliAndroidHelper {
|
||||
static void createShortcut(String id, String uri, String label, String path) {
|
||||
final jId = id.toJString();
|
||||
final jUri = uri.toJString();
|
||||
final jLabel = label.toJString();
|
||||
final jPath = path.toJString();
|
||||
try {
|
||||
AndroidHelper.createShortcut(jId, jUri, jLabel, jPath);
|
||||
} finally {
|
||||
jId.release();
|
||||
jUri.release();
|
||||
jLabel.release();
|
||||
jPath.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
342
lib/utils/android/bindings.g.dart
Normal file
342
lib/utils/android/bindings.g.dart
Normal file
@@ -0,0 +1,342 @@
|
||||
// AUTO GENERATED BY JNIGEN 0.17.0. DO NOT EDIT!
|
||||
|
||||
// ignore_for_file: annotate_overrides
|
||||
// ignore_for_file: argument_type_not_assignable
|
||||
// ignore_for_file: camel_case_extensions
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: constant_identifier_names
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: doc_directive_unknown
|
||||
// ignore_for_file: file_names
|
||||
// ignore_for_file: inference_failure_on_untyped_parameter
|
||||
// ignore_for_file: invalid_internal_annotation
|
||||
// ignore_for_file: invalid_use_of_internal_member
|
||||
// ignore_for_file: library_prefixes
|
||||
// ignore_for_file: lines_longer_than_80_chars
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
// ignore_for_file: no_leading_underscores_for_local_identifiers
|
||||
// ignore_for_file: non_constant_identifier_names
|
||||
// ignore_for_file: only_throw_errors
|
||||
// ignore_for_file: overridden_fields
|
||||
// ignore_for_file: prefer_double_quotes
|
||||
// ignore_for_file: unintended_html_in_doc_comment
|
||||
// ignore_for_file: unnecessary_cast
|
||||
// ignore_for_file: unnecessary_non_null_assertion
|
||||
// ignore_for_file: unnecessary_parenthesis
|
||||
// ignore_for_file: unused_element
|
||||
// ignore_for_file: unused_field
|
||||
// ignore_for_file: unused_import
|
||||
// ignore_for_file: unused_local_variable
|
||||
// ignore_for_file: unused_shown_name
|
||||
// ignore_for_file: use_super_parameters
|
||||
|
||||
import 'dart:core' as core$_;
|
||||
import 'dart:core' show Object, String;
|
||||
|
||||
import 'package:jni/_internal.dart' as jni$_;
|
||||
import 'package:jni/jni.dart' as jni$_;
|
||||
|
||||
const _$jniVersionCheck = jni$_.JniVersionCheck(1, 0);
|
||||
|
||||
/// from: `java.lang.Runnable`
|
||||
extension type Runnable._(jni$_.JObject _$this) implements jni$_.JObject {
|
||||
static final _class = jni$_.JClass.forName(r'java/lang/Runnable');
|
||||
|
||||
/// The type which includes information such as the signature of this class.
|
||||
static const jni$_.JType<Runnable> type = $Runnable$Type$();
|
||||
|
||||
/// Maps a specific port to the implemented interface.
|
||||
static final core$_.Map<core$_.int, $Runnable> _$impls = {};
|
||||
static jni$_.JObjectPtr _$invoke(
|
||||
core$_.int port,
|
||||
jni$_.JObjectPtr descriptor,
|
||||
jni$_.JObjectPtr args,
|
||||
) {
|
||||
return _$invokeMethod(
|
||||
port,
|
||||
jni$_.MethodInvocation.fromAddresses(
|
||||
0,
|
||||
descriptor.address,
|
||||
args.address,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static final jni$_.Pointer<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JObjectPtr Function(jni$_.Int64, jni$_.JObjectPtr, jni$_.JObjectPtr)
|
||||
>
|
||||
>
|
||||
_$invokePointer = jni$_.Pointer.fromFunction(_$invoke);
|
||||
|
||||
static jni$_.Pointer<jni$_.Void> _$invokeMethod(
|
||||
core$_.int $p,
|
||||
jni$_.MethodInvocation $i,
|
||||
) {
|
||||
try {
|
||||
final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
|
||||
final $a = $i.args;
|
||||
if ($d == r'run()V') {
|
||||
_$impls[$p]!.run();
|
||||
return jni$_.nullptr;
|
||||
}
|
||||
} catch (e) {
|
||||
return jni$_.ProtectedJniExtensions.newDartException(e);
|
||||
}
|
||||
return jni$_.nullptr;
|
||||
}
|
||||
|
||||
static void implementIn(
|
||||
jni$_.JImplementer implementer,
|
||||
$Runnable $impl,
|
||||
) {
|
||||
late final jni$_.RawReceivePort $p;
|
||||
$p = jni$_.RawReceivePort(($m) {
|
||||
if ($m == null) {
|
||||
_$impls.remove($p.sendPort.nativePort);
|
||||
$p.close();
|
||||
return;
|
||||
}
|
||||
final $i = jni$_.MethodInvocation.fromMessage($m);
|
||||
final $r = _$invokeMethod($p.sendPort.nativePort, $i);
|
||||
jni$_.ProtectedJniExtensions.returnResult($i.result, $r);
|
||||
});
|
||||
implementer.add(
|
||||
r'java.lang.Runnable',
|
||||
$p,
|
||||
_$invokePointer,
|
||||
[
|
||||
if ($impl.run$async) r'run()V',
|
||||
],
|
||||
);
|
||||
final $a = $p.sendPort.nativePort;
|
||||
_$impls[$a] = $impl;
|
||||
}
|
||||
|
||||
factory Runnable.implement(
|
||||
$Runnable $impl,
|
||||
) {
|
||||
final $i = jni$_.JImplementer();
|
||||
implementIn($i, $impl);
|
||||
return $i.implement<Runnable>();
|
||||
}
|
||||
}
|
||||
|
||||
extension Runnable$$Methods on Runnable {
|
||||
static final _id_run = Runnable._class.instanceMethodId(
|
||||
r'run',
|
||||
r'()V',
|
||||
);
|
||||
|
||||
static final _run =
|
||||
jni$_.ProtectedJniExtensions.lookup<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>
|
||||
>('globalEnv_CallVoidMethod')
|
||||
.asFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `public abstract void run()`
|
||||
void run() {
|
||||
final _$$selfRef = reference;
|
||||
_run(_$$selfRef.pointer, _id_run.pointer).check();
|
||||
}
|
||||
}
|
||||
|
||||
abstract base mixin class $Runnable {
|
||||
factory $Runnable({
|
||||
required void Function() run,
|
||||
core$_.bool run$async,
|
||||
}) = _$Runnable;
|
||||
|
||||
void run();
|
||||
core$_.bool get run$async => false;
|
||||
}
|
||||
|
||||
final class _$Runnable with $Runnable {
|
||||
_$Runnable({
|
||||
required void Function() run,
|
||||
this.run$async = false,
|
||||
}) : _run = run;
|
||||
|
||||
final void Function() _run;
|
||||
final core$_.bool run$async;
|
||||
|
||||
void run() {
|
||||
return _run();
|
||||
}
|
||||
}
|
||||
|
||||
final class $Runnable$Type$ extends jni$_.JType<Runnable> {
|
||||
@jni$_.internal
|
||||
const $Runnable$Type$();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
String get signature => r'Ljava/lang/Runnable;';
|
||||
}
|
||||
|
||||
/// from: `com.example.piliplus.AndroidHelper`
|
||||
extension type AndroidHelper._(jni$_.JObject _$this) implements jni$_.JObject {
|
||||
static final _class = jni$_.JClass.forName(
|
||||
r'com/example/piliplus/AndroidHelper',
|
||||
);
|
||||
|
||||
/// The type which includes information such as the signature of this class.
|
||||
static const jni$_.JType<AndroidHelper> type = $AndroidHelper$Type$();
|
||||
static final _id_back = _class.staticMethodId(
|
||||
r'back',
|
||||
r'()V',
|
||||
);
|
||||
|
||||
static final _back =
|
||||
jni$_.ProtectedJniExtensions.lookup<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>
|
||||
>('globalEnv_CallStaticVoidMethod')
|
||||
.asFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `static public void back()`
|
||||
static void back() {
|
||||
final _$$classRef = _class.reference;
|
||||
_back(_$$classRef.pointer, _id_back.pointer).check();
|
||||
}
|
||||
|
||||
static final _id_sdkInt = _class.staticMethodId(
|
||||
r'sdkInt',
|
||||
r'()I',
|
||||
);
|
||||
|
||||
static final _sdkInt =
|
||||
jni$_.ProtectedJniExtensions.lookup<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JniResult Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>
|
||||
>('globalEnv_CallStaticIntMethod')
|
||||
.asFunction<
|
||||
jni$_.JniResult Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `static public int sdkInt()`
|
||||
static core$_.int sdkInt() {
|
||||
final _$$classRef = _class.reference;
|
||||
return _sdkInt(_$$classRef.pointer, _id_sdkInt.pointer).integer;
|
||||
}
|
||||
|
||||
static final _id_openLinkVerifySettings = _class.staticMethodId(
|
||||
r'openLinkVerifySettings',
|
||||
r'()V',
|
||||
);
|
||||
|
||||
static final _openLinkVerifySettings =
|
||||
jni$_.ProtectedJniExtensions.lookup<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>
|
||||
>('globalEnv_CallStaticVoidMethod')
|
||||
.asFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `static public void openLinkVerifySettings()`
|
||||
static void openLinkVerifySettings() {
|
||||
final _$$classRef = _class.reference;
|
||||
_openLinkVerifySettings(
|
||||
_$$classRef.pointer,
|
||||
_id_openLinkVerifySettings.pointer,
|
||||
).check();
|
||||
}
|
||||
|
||||
static final _id_createShortcut = _class.staticMethodId(
|
||||
r'createShortcut',
|
||||
r'(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V',
|
||||
);
|
||||
|
||||
static final _createShortcut =
|
||||
jni$_.ProtectedJniExtensions.lookup<
|
||||
jni$_.NativeFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
jni$_.VarArgs<
|
||||
(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
)
|
||||
>,
|
||||
)
|
||||
>
|
||||
>('globalEnv_CallStaticVoidMethod')
|
||||
.asFunction<
|
||||
jni$_.JThrowablePtr Function(
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.JMethodIDPtr,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
jni$_.Pointer<jni$_.Void>,
|
||||
)
|
||||
>();
|
||||
|
||||
/// from: `static public void createShortcut(java.lang.String id, java.lang.String uri, java.lang.String label, java.lang.String icon)`
|
||||
static void createShortcut(
|
||||
jni$_.JString id,
|
||||
jni$_.JString uri,
|
||||
jni$_.JString label,
|
||||
jni$_.JString icon,
|
||||
) {
|
||||
final _$$classRef = _class.reference;
|
||||
final _$id = id.reference;
|
||||
final _$uri = uri.reference;
|
||||
final _$label = label.reference;
|
||||
final _$icon = icon.reference;
|
||||
_createShortcut(
|
||||
_$$classRef.pointer,
|
||||
_id_createShortcut.pointer,
|
||||
_$id.pointer,
|
||||
_$uri.pointer,
|
||||
_$label.pointer,
|
||||
_$icon.pointer,
|
||||
).check();
|
||||
}
|
||||
}
|
||||
|
||||
final class $AndroidHelper$Type$ extends jni$_.JType<AndroidHelper> {
|
||||
@jni$_.internal
|
||||
const $AndroidHelper$Type$();
|
||||
|
||||
@jni$_.internal
|
||||
@core$_.override
|
||||
String get signature => r'Lcom/example/piliplus/AndroidHelper;';
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import 'package:PiliPlus/utils/android/bindings.g.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:flutter/widgets.dart' show WidgetsBinding, Size;
|
||||
|
||||
abstract final class DeviceUtils {
|
||||
static late int sdkInt;
|
||||
static final int sdkInt = AndroidHelper.sdkInt();
|
||||
|
||||
static bool get isTablet {
|
||||
return size.shortestSide >= 600;
|
||||
|
||||
@@ -46,11 +46,11 @@ abstract final class ReplyUtils {
|
||||
required int type,
|
||||
required int id,
|
||||
required String message,
|
||||
dynamic root,
|
||||
dynamic parent,
|
||||
dynamic ctime,
|
||||
List? pictures,
|
||||
dynamic mid,
|
||||
required int root,
|
||||
required int parent,
|
||||
required int ctime,
|
||||
required List pictures,
|
||||
required int mid,
|
||||
bool isManual = false,
|
||||
}) async {
|
||||
// CommAntifraud
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import 'dart:convert' show JsonEncoder, base64;
|
||||
import 'dart:math' show Random;
|
||||
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:catcher_2/catcher_2.dart';
|
||||
import 'package:flutter/services.dart'
|
||||
show Clipboard, ClipboardData, MethodChannel;
|
||||
import 'package:flutter/services.dart' show Clipboard, ClipboardData;
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
|
||||
abstract final class Utils {
|
||||
static final random = Random();
|
||||
|
||||
static const channel = MethodChannel(Constants.appName);
|
||||
|
||||
static const jsonEncoder = JsonEncoder.withIndent(' ');
|
||||
|
||||
static final numericRegex = RegExp(r'^[\d\.]+$');
|
||||
|
||||
19
pubspec.lock
19
pubspec.lock
@@ -269,6 +269,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
cli_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_config
|
||||
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -948,7 +956,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
jni:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: jni
|
||||
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
|
||||
@@ -963,6 +971,15 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
jnigen:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
path: "pkgs/jnigen"
|
||||
ref: HEAD
|
||||
resolved-ref: "14f4ce655c0cebb203777b8200303a9bc1f0b04e"
|
||||
url: "https://github.com/dart-lang/native.git"
|
||||
source: git
|
||||
version: "0.17.0-wip"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -112,6 +112,7 @@ dependencies:
|
||||
image_cropper: ^12.0.0
|
||||
image_picker: ^1.1.2
|
||||
intl: ^0.20.2
|
||||
jni: ^1.0.0
|
||||
json_annotation: ^4.11.0
|
||||
live_photo_maker:
|
||||
git:
|
||||
@@ -244,6 +245,10 @@ dev_dependencies:
|
||||
flutter_launcher_icons: ^0.14.4
|
||||
flutter_lints: ^6.0.0
|
||||
flutter_native_splash: ^2.4.6
|
||||
jnigen:
|
||||
git:
|
||||
url: https://github.com/dart-lang/native.git
|
||||
path: pkgs/jnigen
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: true
|
||||
|
||||
1
tool/README.md
Normal file
1
tool/README.md
Normal file
@@ -0,0 +1 @@
|
||||
run `dart run tool/jnigen.dart`
|
||||
23
tool/jnigen.dart
Normal file
23
tool/jnigen.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:jnigen/jnigen.dart';
|
||||
|
||||
void main(List<String> args) {
|
||||
final packageRoot = Platform.script.resolve('../');
|
||||
generateJniBindings(
|
||||
Config(
|
||||
outputConfig: OutputConfig(
|
||||
dartConfig: DartCodeOutputConfig(
|
||||
path: packageRoot.resolve('lib/utils/android/bindings.g.dart'),
|
||||
structure: .singleFile,
|
||||
),
|
||||
),
|
||||
androidSdkConfig: AndroidSdkConfig(addGradleDeps: true),
|
||||
sourcePath: [packageRoot.resolve('android/app/src/main/java')],
|
||||
classes: [
|
||||
'com.example.piliplus',
|
||||
'java.lang.Runnable',
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user