Commit 790e34e1 by 徐健

增加ydl-flutter-base模块与公共通道

parent d3553a5a
......@@ -189,6 +189,8 @@ dependencies {
// api "com.ydl:m-consultant-api:0.0.2"
// api 'com.ydl:m-consultant-module-ydl:0.0.18@aar'
implementation project(':ydl-flutter-base')
api (project(':ydl-platform')){
transitive = true
}
......
......@@ -5,8 +5,6 @@ import android.app.Application;
import android.content.Context;
import android.content.Intent;
import com.ydl.component.single.CustomBinaryMessagerImpl;
import com.ydl.component.single.YDLCommonPlugin;
import com.ydl.devicesidlib.DeviceIDHelper;
import com.ydl.media.audio.PlayService;
import com.ydl.ydlcommon.base.delegate.IAppLifecycles;
......@@ -15,8 +13,6 @@ import com.yidianling.course.lifeCallback.CoursePlayLifecycle;
import org.jetbrains.annotations.NotNull;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.view.FlutterMain;
/**
......@@ -24,6 +20,7 @@ import io.flutter.view.FlutterMain;
* Des:
*/
public class DemoAppLifecycles implements IAppLifecycles {
@Override
public void attachBaseContext(@NotNull Context base) {
......@@ -39,7 +36,6 @@ public class DemoAppLifecycles implements IAppLifecycles {
//Flutter 初始化需要在主线程中执行
FlutterMain.startInitialization(application);
initFlutterChannel();
Intent intent = new Intent(application, PlayService.class);
application.startService(intent);
......@@ -47,14 +43,6 @@ public class DemoAppLifecycles implements IAppLifecycles {
application.registerActivityLifecycleCallbacks(new CoursePlayLifecycle());
}
/**
* 初始化一个公共channel
*/
private void initFlutterChannel() {
YDLCommonPlugin commonPlugin = new YDLCommonPlugin();
new MethodChannel(CustomBinaryMessagerImpl.Companion.getINSTANCE(), commonPlugin.CHANNEL).setMethodCallHandler(commonPlugin);
}
@Override
public void onTerminate(@NotNull Application application) {
......
package com.ydl.component.single
import io.flutter.plugin.common.BinaryMessenger
import java.nio.ByteBuffer
/**
* Created by xj on 2019/11/20.
*/
class CustomBinaryMessagerImpl: BinaryMessenger {
override fun setMessageHandler(p0: String, p1: BinaryMessenger.BinaryMessageHandler?) {
}
override fun send(p0: String, p1: ByteBuffer?) {
}
override fun send(p0: String, p1: ByteBuffer?, p2: BinaryMessenger.BinaryReply?) {
}
companion object {
val INSTANCE by lazy { CustomBinaryMessagerImpl() }
}
}
\ No newline at end of file
......@@ -73,6 +73,7 @@ dependencies {
api project(":ydl-platform")
api project(":ydl-media")
api project(":ydl-pay")
implementation project(':ydl-flutter-base')
} else {
//发布时使用
......@@ -86,6 +87,6 @@ dependencies {
api(rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
api rootProject.ext.dependencies["ydl-flutter"]
}
api rootProject.ext.dependencies["ydl-flutter"]
}
......@@ -2,12 +2,10 @@ package com.yidianling.course
import CoursePlugin
import android.annotation.SuppressLint
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.view.View
import com.alibaba.android.arouter.launcher.ARouter
import com.example.fm_plugin.base.BaseFlutterFragment
import com.channel.ydl_flutter_base.base.BaseFlutterFragment
import com.google.gson.Gson
import com.ydl.ydl_router.manager.YDLRouterManager
import com.ydl.ydlcommon.data.http.BaseResponse
......
......@@ -3,7 +3,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Handler
import android.text.TextUtils
import com.example.fm_plugin.base.BaseFlutterFragment
import com.channel.ydl_flutter_base.base.BaseFlutterFragment
import com.lzf.easyfloat.permission.PermissionUtils
import com.ydl.media.audio.AudioPlayer
import com.ydl.media.audio.model.Music
......
package com.yidianling.course.flutterPlugin
import android.util.Log
import com.channel.ydl_flutter_base.base.BaseFlutterFragment
import com.example.fm_plugin.base.FlutterFragment
import io.flutter.plugin.common.EventChannel
import io.flutter.view.FlutterView
......@@ -16,10 +16,10 @@ object CourseSendPlugin {
private var messageChannel: EventChannel? = null
const val CHANNEL: String = "base/channel/native/post"
private var mFragment: FlutterFragment? = null
private var mFragment: BaseFlutterFragment? = null
private var eventSink: EventChannel.EventSink? = null
fun initContext(fragment: FlutterFragment, view: FlutterView): CourseSendPlugin {
fun initContext(fragment: BaseFlutterFragment, view: FlutterView): CourseSendPlugin {
mFragment = fragment
messageChannel = EventChannel(view, CHANNEL)
messageChannel!!.setStreamHandler(object : EventChannel.StreamHandler {
......@@ -39,11 +39,11 @@ object CourseSendPlugin {
}
fun sendRequestData(){
fun sendRequestData() {
eventSink!!.success("requestData")
}
fun sendLoginSuccess(){
fun sendLoginSuccess() {
eventSink!!.success("loginSuccess")
}
......
......@@ -66,13 +66,15 @@ dependencies {
//开发时使用
api project(":ydl-platform")
implementation project(':ydl-media')
implementation project(':ydl-flutter-base')
} else {
//发布时使用
api rootProject.ext.dependencies["ydl-media"]
api rootProject.ext.dependencies["ydl-flutter"]
api (rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
//TODO xujian flutter
}
api rootProject.ext.dependencies["ydl-flutter"]
}
package com.yidianling.muse.activity
import com.alibaba.android.arouter.facade.annotation.Route
import com.example.fm_plugin.base.BaseFlutterActivity
import com.channel.ydl_flutter_base.base.BaseFlutterActivity
import com.ydl.media.audio.AudioPlayer
import com.ydl.ydlcommon.router.IYDLRouterConstant
import com.yidianling.muse.handler.MusePlugin
......
......@@ -75,6 +75,7 @@ dependencies {
//开发时使用
api project(':ydl-webview')
api project(':ydl-platform')
implementation project(':ydl-flutter-base')
implementation modularPublication('com.ydl:m-test-api')
implementation modularPublication('com.ydl:m-user-api')
}else {
......
package com.yidianling.tests.home
import com.alibaba.android.arouter.facade.annotation.Route
import com.ydl.ydl_flutter.flutter.base.BaseFlutterActivity
import com.channel.ydl_flutter_base.base.BaseFlutterActivity
import com.yidianling.tests.home.plugin.TestPlugin
import org.json.JSONObject
......@@ -10,7 +10,7 @@ import org.json.JSONObject
* Created by xj on 2019/11/19.
*/
@Route(path = "/ceshi/home")
class NewTestHomeActivity: BaseFlutterActivity() {
class NewTestHomeActivity : BaseFlutterActivity() {
override fun initialRoute(): String {
return "native/test/home"
}
......
include ':app',":router", ':ydl-net', ':ydl-utils', ':ydl-platform', ':ydl-webview',
include ':app', ':ydl-flutter-base',":router", ':ydl-net', ':ydl-utils', ':ydl-platform', ':ydl-webview',
':m-confide', ':m-audioim',':ydl-media',":m-user", ':m-consultant', ':m-muse',
':m-fm', ':m-tests',":m-course", ':ydl-pay'
......
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
buildToolsVersion rootProject.ext.android["buildToolsVersion"]
defaultConfig {
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
versionCode 1
versionName "1.0"
multiDexEnabled true
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
flavorDimensions "versionCode"
}
lintOptions {
abortOnError false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
}
dependencies {
api fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation "com.alibaba:arouter-api:$arouter_api"
// 注意此处的依赖方式:kotlin中使用和java中使用方式有不同
kapt "com.alibaba:arouter-compiler:$arouter_compiler"
if (rootProject.ext.dev_mode){
//开发时使用
implementation project(":ydl-platform")
api fileTree(include: ['*.aar'], dir: 'aars')
} else {
//发布时使用
api (rootProject.ext.dependencies["ydl-platform"]) {
transitive = true
}
//TODO xujian 把flutteraar和spaar上传
}
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
package com.channel.xj.ydl_flutter_base;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.channel.xj.m_flutter_base.test", appContext.getPackageName());
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.channel.ydl_flutter_base" />
package com.channel.ydl_flutter_base.base
import android.content.Context
import android.content.Intent
import android.graphics.PixelFormat
import android.os.Bundle
import android.util.AttributeSet
import android.view.WindowManager
import com.channel.ydl_flutter_base.plugin.YDLCommonPlugin
import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.view.FlutterView
import org.json.JSONObject
/**
* flutter 页面基类
* Created by xj on 2019/9/30.
*/
abstract class BaseFlutterActivity : FlutterActivity() {
companion object {
const val ROUTE_PAGE = "route" //路由
/**
* 路由传递过来的参数
*/
const val ROUTER_PARAMS = "routerParam"
}
override fun createFlutterView(context: Context?): FlutterView {
val matchParent = WindowManager.LayoutParams(-1, -1)
val nativeView = this.createFlutterNativeView()
val flutterView = FlutterView(this, null as AttributeSet?, nativeView)
flutterView.layoutParams = matchParent
this.setContentView(flutterView)
//这个action必加,不然无法在flutter端获取route参数值
intent.action = Intent.ACTION_RUN
/**
* 在这边初始化route
*/
intent.putExtra(ROUTE_PAGE, initialRoute())
//渲染优化(优化一丢丢几乎看不出来)
flutterView.setZOrderOnTop(true)
flutterView.holder.setFormat(PixelFormat.TRANSLUCENT)
return flutterView
}
public override fun onCreate( savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
/**
* 获取统一路由传递过来的参数并初始化交互通道
*/
val json = intent.getStringExtra(ROUTER_PARAMS)
var jb = JSONObject()
if (json!=null){
jb = JSONObject(json)
}
YDLCommonPlugin.activityRegister(this)
initChannelPlugin(jb)
}
/**
* 路由,例 "/native/muse/home"
*/
abstract fun initialRoute(): String
/**
* 初始化flutter channel插件
*/
abstract fun initChannelPlugin(jsonObject: JSONObject)
}
\ No newline at end of file
package com.channel.ydl_flutter_base.base
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import com.channel.ydl_flutter_base.plugin.YDLCommonPlugin
import io.flutter.view.FlutterView
/**
* flutter fragment 基类
* Created by xj on 2019/9/30.
*/
abstract class BaseFlutterFragment : FlutterFragment() {
private var mFlutterView: FlutterView? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): FlutterView {
mFlutterView= Flutter.createView(
activity!!,
lifecycle,
initialRoute())
YDLCommonPlugin.fragmentRegister(this, mFlutterView!!)
initChannelPlugin(mFlutterView!!)
return mFlutterView!!
}
/**
* 路由,例 "quick_reply"
*/
abstract fun initialRoute(): String
/**
* 初始化flutter channel插件
*/
abstract fun initChannelPlugin(flutterView: FlutterView)
}
package com.channel.ydl_flutter_base.base;
import android.app.Activity;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.example.fm_plugin.base.FlutterFragment;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.StringCodec;
import io.flutter.plugins.GeneratedPluginRegistrant;
import io.flutter.view.FlutterMain;
import io.flutter.view.FlutterNativeView;
import io.flutter.view.FlutterRunArguments;
import io.flutter.view.FlutterView;
/**
* Main entry point for using Flutter in Android applications.
*
* <p><strong>Warning:</strong> This file is auto-generated by Flutter tooling.
* DO NOT EDIT.</p>
*/
public final class Flutter {
private Flutter() {
// to prevent instantiation
}
/**
* Initiates the Dart VM. Calling this method at an early point may help decreasing time to first
* frame for a subsequently created {@link FlutterView}.
*
* @param applicationContext the application's {@link Context}
*/
public static void startInitialization(@NonNull Context applicationContext) {
FlutterMain.startInitialization(applicationContext);
}
/**
* Creates a {@link com.example.fm_plugin.base.FlutterFragment} managing a {@link FlutterView}. The optional
* initial route string will be made available to the Dart code
* (via {@code window.defaultRouteName}) and may be used to determine which widget
* should be displayed in the view. The default initialRoute is "/".
*
* @param initialRoute an initial route {@link String}, or null
* @return a {@link com.example.fm_plugin.base.FlutterFragment}
*/
@NonNull
public static com.example.fm_plugin.base.FlutterFragment createFragment(String initialRoute) {
final com.example.fm_plugin.base.FlutterFragment fragment = new com.example.fm_plugin.base.FlutterFragment();
final Bundle args = new Bundle();
args.putString(FlutterFragment.ARG_ROUTE, initialRoute);
fragment.setArguments(args);
return fragment;
}
/**
* Creates a {@link FlutterView} linked to the specified {@link Activity} and {@link Lifecycle}.
* The optional initial route string will be made available to the Dart code (via
* {@code window.defaultRouteName}) and may be used to determine which widget should be displayed
* in the view. The default initialRoute is "/".
*
* @param activity an {@link Activity}
* @param lifecycle a {@link Lifecycle}
* @param initialRoute an initial route {@link String}, or null
* @return a {@link FlutterView}
*/
@NonNull
public static FlutterView createView(@NonNull final Activity activity, @NonNull final Lifecycle lifecycle, final String initialRoute) {
FlutterMain.startInitialization(activity.getApplicationContext());
FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), null);
final FlutterNativeView nativeView = new FlutterNativeView(activity);
final FlutterView flutterView = new FlutterView(activity, null, nativeView) {
private final BasicMessageChannel<String> lifecycleMessages = new BasicMessageChannel<>(this, "flutter/lifecycle", StringCodec.INSTANCE);
@Override
public void onFirstFrame() {
super.onFirstFrame();
setAlpha(1.0f);
}
@Override
public void onPostResume() {
// Overriding default behavior to avoid dictating system UI via PlatformPlugin.
lifecycleMessages.send("AppLifecycleState.resumed");
}
};
if (initialRoute != null) {
flutterView.setInitialRoute(initialRoute);
}
lifecycle.addObserver(new LifecycleObserver() {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
final FlutterRunArguments arguments = new FlutterRunArguments();
arguments.bundlePath = FlutterMain.findAppBundlePath(activity.getApplicationContext());
arguments.entrypoint = "main";
flutterView.runFromBundle(arguments);
GeneratedPluginRegistrant.registerWith(flutterView.getPluginRegistry());
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
flutterView.onStart();
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
flutterView.onPostResume();
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
flutterView.onPause();
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
flutterView.onStop();
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
flutterView.destroy();
}
});
flutterView.setAlpha(0.0f);
return flutterView;
}
}
package com.channel.ydl_flutter_base.base;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.example.fm_plugin.base.Flutter;
import io.flutter.view.FlutterView;
/**
* A {@link Fragment} managing a {@link FlutterView}.
*
* <p><strong>Warning:</strong> This file is auto-generated by Flutter tooling.
* DO NOT EDIT.</p>
*/
public class FlutterFragment extends Fragment {
public static final String ARG_ROUTE = "route";
private String mRoute = "/";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mRoute = getArguments().getString(ARG_ROUTE);
}
}
@Override
public void onInflate(Context context, AttributeSet attrs, Bundle savedInstanceState) {
super.onInflate(context, attrs, savedInstanceState);
}
@Override
public FlutterView onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return Flutter.createView(getActivity(), getLifecycle(), mRoute);
}
}
package com.ydl.component.single
package com.channel.ydl_flutter_base.plugin
import android.text.TextUtils
import com.ydl.component.BuildConfig
import com.channel.ydl_flutter_base.base.BaseFlutterFragment
import com.ydl.ydlcommon.base.BaseApp
import com.ydl.ydlcommon.data.PlatformDataManager
import com.ydl.ydlcommon.modular.ModularServiceManager
import com.yidianling.common.BuildConfig
import com.yidianling.common.tools.RxDeviceTool
import io.flutter.app.FlutterActivity
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.view.FlutterView
/**
* Created by xj on 2019/11/19.
*/
class YDLCommonPlugin : MethodChannel.MethodCallHandler {
private var mActivity: FlutterActivity? = null
private constructor(activity: FlutterActivity) {
mActivity = activity
}
private var mFragment: BaseFlutterFragment? = null
private constructor(fragment: BaseFlutterFragment) {
mFragment = fragment
}
companion object {
const val CHANNEL: String = "lib/common/channel"
const val GETPUBLICPARAMAS: String = "getPublicParamas"
//activity注册
fun activityRegister(activity: FlutterActivity) {
MethodChannel(activity.flutterView, CHANNEL).setMethodCallHandler(YDLCommonPlugin(activity))
}
//fragment注册
fun fragmentRegister(fragment: BaseFlutterFragment, flutterView: FlutterView) {
MethodChannel(flutterView, CHANNEL).setMethodCallHandler(YDLCommonPlugin(fragment))
}
}
override fun onMethodCall(methodCall: MethodCall, result: MethodChannel.Result) {
......
<resources>
<string name="app_name">m-flutter-base</string>
</resources>
package com.channel.xj.ydl_flutter_base;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
......@@ -64,7 +64,7 @@ android {
}
dependencies {
api fileTree(include: ['*.aar'], dir: 'libs')
api fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment