implement gomobile interface for start and parial work on GetProfiles

This commit is contained in:
Dan Ballard 2021-01-12 21:47:20 -08:00
parent c1f7556636
commit c2aa0dfb4a
7 changed files with 190 additions and 68 deletions

View File

@ -0,0 +1,46 @@
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import androidx.annotation.NonNull
import android.content.Context
//import libCwtch.LibCwtch
/* References:
more detailed kotlin / flutter method channel example:
https://stablekernel.com/article/flutter-platform-channels-quick-start/
kotlin / flutter plugin:
https://github.com/flutter/samples -- experimental/federated_plugin/federated_plugin
*/
/*
class FederatedPlugin : FlutterPlugin, MethodCallHandler {
private lateinit var channel: MethodChannel
private var context: Context? = null
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cwtch")
channel.setMethodCallHandler(this)
context = flutterPluginBinding.applicationContext
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"Start" -> {
val appDir = (call.arguments as? String) ?: "";
val tor = (call.arguments as? String) ?: "tor";
result.success(LibCwtch.Start(appDir, tor))
?: result.error("Failed to start cwtch", "", null);
}
else -> result.notImplemented()
}
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
context = null
}
}*/

View File

@ -4,37 +4,55 @@ import io.flutter.embedding.android.FlutterActivity
import androidx.annotation.NonNull
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import android.content.pm.PackageManager
import android.util.Log
import cwtch.Cwtch
class MainActivity: FlutterActivity() {
private val CHANNEL = "test.flutter.dev/applicationInfo"
private val CALL_NATIVE_LIB_DIR = "getNativeLibDir"
private val CHANNEL_APP_INFO = "test.flutter.dev/applicationInfo"
private val CALL_APP_INFO = "getNativeLibDir"
private val CHANNEL_CWTCH = "cwtch"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
// Note: this method is invoked on the main thread.
call, result ->
if (call.method == CALL_NATIVE_LIB_DIR) {
val nativeLibDir = getNativeLibDir()
// Note: this method is invoked on the main thread.
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_APP_INFO).setMethodCallHandler { call, result -> handleAppInfo(call, result) }
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL_CWTCH).setMethodCallHandler { call, result -> handleCwtch(call, result) }
}
if (nativeLibDir != "") {
result.success(nativeLibDir)
} else {
result.error("UNAVAILABLE", "nativeLibDir not available.", null)
}
} else {
result.notImplemented()
}
private fun handleAppInfo(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
CALL_APP_INFO -> result.success(getNativeLibDir())
?: result.error("Unavailable", "nativeLibDir not available", null);
else -> result.notImplemented()
}
}
private fun getNativeLibDir(): String {
val ainfo = this.applicationContext.packageManager.getApplicationInfo(
"com.example.flutter_app", // Must be app name
PackageManager.GET_SHARED_LIBRARY_FILES)
return ainfo.nativeLibraryDir
}
private fun handleCwtch(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"Start" -> {
Log.i("MainActivity.kt", "handleAppInfo Start")
val appDir = (call.argument("appDir") as? String) ?: "";
val torPath = (call.argument("torPath") as? String) ?: "tor";
Log.i("MainActivity.kt", " appDir: '" + appDir + "' torPath: '" + torPath + "'")
Cwtch.startCwtch(appDir, torPath)
}
else -> result.notImplemented()
}
}
}

Binary file not shown.

View File

@ -1,12 +1,12 @@
abstract class Cwtch {
void Start(String appDir, String torPath) ;
void Start();
void SelectProfile(String onion);
String ACNEvents();
String ContactEvents();
String GetProfiles();
Future<String> GetProfiles();
String GetContacts(String onion);
int NumMessages(String profile, String handle);

View File

@ -1,4 +1,6 @@
import 'dart:ffi';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:ffi/ffi.dart';
import 'package:flutter_app/cwtch/cwtch.dart';
@ -7,8 +9,8 @@ import 'package:flutter_app/cwtch/cwtch.dart';
/// Cwtch API ///
/////////////////////
typedef start_cwtch_function = Void Function(Pointer<Utf8> str, Int32 length);
typedef StartCwtchFn = void Function(Pointer<Utf8> dir, int len);
typedef start_cwtch_function = Void Function(Pointer<Utf8> str, Int32 length, Pointer<Utf8> str2, Int32 length2);
typedef StartCwtchFn = void Function(Pointer<Utf8> dir, int len, Pointer<Utf8> tor, int torLen);
typedef access_cwtch_eventbus_function = Void Function();
typedef NextEventFn = void Function();
@ -37,15 +39,25 @@ class CwtchFfi implements Cwtch {
library = DynamicLibrary.open("libCwtch.so");
}
void Start(String appDir, String torPath) {
var startCwtchC = library.lookup<NativeFunction<start_cwtch_function>>("StartCwtch");
void Start() {
String home = "";
Map<String, String> envVars = Platform.environment;
if (Platform.isLinux) {
home = envVars['HOME'];
} else if (Platform.isWindows) {
home = envVars['UserProfile'];
}
var cwtchDir = path.join(home, ".cwtch/dev/");
print("cwtchDir $cwtchDir");
var startCwtchC = library.lookup<NativeFunction<start_cwtch_function>>("c_StartCwtch");
// ignore: non_constant_identifier_names
final StartCwtch = startCwtchC.asFunction<StartCwtchFn>();
StartCwtch(Utf8.toUtf8(appDir), appDir.length);
StartCwtch(Utf8.toUtf8(cwtchDir), cwtchDir.length, Utf8.toUtf8(""), 0);
}
void SelectProfile(String onion) {
var selectProfileC = library.lookup<NativeFunction<get_json_blob_string_function>>("SelectProfile");
var selectProfileC = library.lookup<NativeFunction<get_json_blob_string_function>>("c_SelectProfile");
// ignore: non_constant_identifier_names
final SelectProfile = selectProfileC.asFunction<GetJsonBlobStringFn>();
@ -54,7 +66,7 @@ class CwtchFfi implements Cwtch {
String ACNEvents() {
var acnEventsC = library.lookup<NativeFunction<acn_events_function>>(
"ACNEvents");
"c_ACNEvents");
// ignore: non_constant_identifier_names
final ACNEvents = acnEventsC.asFunction<ACNEventsFn>();
@ -66,7 +78,7 @@ class CwtchFfi implements Cwtch {
String ContactEvents() {
var acnEventsC = library.lookup<NativeFunction<acn_events_function>>(
"ContactEvents");
"c_ContactEvents");
// ignore: non_constant_identifier_names
final ContactEvents = acnEventsC.asFunction<ACNEventsFn>();
@ -75,8 +87,8 @@ class CwtchFfi implements Cwtch {
return event;
}
String GetProfiles() {
var getProfilesC = library.lookup<NativeFunction<get_json_blob_void_function>>("GetProfiles");
Future<String> GetProfiles() async {
var getProfilesC = library.lookup<NativeFunction<get_json_blob_void_function>>("c_GetProfiles");
// ignore: non_constant_identifier_names
final GetProfiles = getProfilesC.asFunction<GetJsonBlobVoidFn>();
@ -86,7 +98,7 @@ class CwtchFfi implements Cwtch {
}
String GetContacts(String onion) {
var getContactsC = library.lookup<NativeFunction<get_json_blob_string_function>>("GetContacts");
var getContactsC = library.lookup<NativeFunction<get_json_blob_string_function>>("c_GetContacts");
// ignore: non_constant_identifier_names
final GetContacts = getContactsC.asFunction<GetJsonBlobStringFn>();
Pointer<Utf8> jsonContactBytes = GetContacts(Utf8.toUtf8(onion), onion.length);
@ -95,7 +107,7 @@ class CwtchFfi implements Cwtch {
}
int NumMessages(String profile, String handle) {
var numMessagesC = library.lookup<NativeFunction<get_int_from_str_str_function>>("NumMessages");
var numMessagesC = library.lookup<NativeFunction<get_int_from_str_str_function>>("c_NumMessages");
// ignore: non_constant_identifier_names
final NumMessages = numMessagesC.asFunction<GetIntFromStrStrFn>();
@ -104,7 +116,7 @@ class CwtchFfi implements Cwtch {
}
String GetMessage(String profile, String handle, int index) {
var getMessageC = library.lookup<NativeFunction<get_json_blob_from_str_str_int_function>>("GetMessage");
var getMessageC = library.lookup<NativeFunction<get_json_blob_from_str_str_int_function>>("c_GetMessage");
// ignore: non_constant_identifier_names
final GetMessage = getMessageC.asFunction<GetJsonBlobFromStrStrIntFn>();

77
lib/cwtch/gomobile.dart Normal file
View File

@ -0,0 +1,77 @@
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'package:path/path.dart' as path;
import 'cwtch.dart';
/*
import 'package:federated_plugin_platform_interface/federated_plugin_platform_interface.dart';
/// It uses [FederatedPluginInterface]
Future startCwtch() async {
return await FederatedPluginInterface.instance.startCwtch();
}
*/
class CwtchGomobile implements Cwtch {
static const appInfoPlatform = const MethodChannel('test.flutter.dev/applicationInfo');
static const cwtchPlatform = const MethodChannel('cwtch');
var androidLibraryDir = "";
var androidHomeDirectory = "";
CwtchGomobile() {
print("CwtchGomobile()");
/*getApplicationDocumentsDirectory().then((directory) =>
{
print("androidHomeDir = $directory"),
androidHomeDirectory = directory.path
});
appInfoPlatform.invokeMethod('getNativeLibDir').then((value) =>
{
print("nativeLibraryDir = $value"),
androidLibraryDir = value
});*/
}
void Start() async {
var androidHome = getApplicationDocumentsDirectory();
var androidLibDir = appInfoPlatform.invokeMethod('getNativeLibDir');
var cwtchDir = path.join((await androidHome).path, ".cwtch/dev/");
String torPath = path.join(await androidLibDir, "libtor.so");
print("gomobile.dart: Start($cwtchDir, $torPath)");
cwtchPlatform.invokeMethod("Start", {"appDir": cwtchDir, "torPath": torPath});
}
void SelectProfile(String onion) {
}
String ACNEvents() {
return "{}";
}
String ContactEvents() {
return "{}";
}
Future<String> GetProfiles() {
return cwtchPlatform.invokeMethod("GetProfiles");
}
String GetContacts(String onion) {
return "{}";
}
int NumMessages(String profile, String handle) {
return 0;
}
String GetMessage(String profile, String handle, int index) {
return "{}";
}
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_app/cwtch/ffi.dart';
import 'package:flutter_app/cwtch/gomobile.dart';
import 'package:provider/provider.dart';
import 'cwtch/cwtch.dart';
import 'model.dart';
@ -24,55 +25,23 @@ class FlwtchState extends State<Flwtch> {
Cwtch cwtch;
AppModel appStatus;
static const appInfoPlatform = const MethodChannel('test.flutter.dev/applicationInfo');
var androidLibraryDir = "";
var androidHomeDirectory = "";
@override
initState() {
super.initState();
if (Platform.isAndroid) {
getApplicationDocumentsDirectory().then((directory) =>
{
setState(() {
print("androidHomeDir = $directory");
androidHomeDirectory = directory.path;
})
});
appInfoPlatform.invokeMethod('getNativeLibDir').then((value) =>
{
setState(() {
print("nativeLibraryDir = $value");
androidLibraryDir = value;
})
});
cwtch = CwtchGomobile();
} else {
cwtch = CwtchFfi();
}
}
@override
Widget build(BuildContext context) {
cwtch = CwtchFfi();
appStatus = AppModel(cwtch: cwtch);
String home = "";
Map<String, String> envVars = Platform.environment;
if (Platform.isMacOS) {
home = envVars['HOME'];
} else if (Platform.isLinux) {
home = envVars['HOME'];
} else if (Platform.isWindows) {
home = envVars['UserProfile'];
} else if (Platform.isAndroid) {
home = androidHomeDirectory;
}
var cwtchDir = path.join(home, ".cwtch/dev/");
print("cwtchDir $cwtchDir");
cwtch.Start(cwtchDir, "tor");
cwtch.Start();
return Provider<FlwtchState>(
create: (_) => this,