現(xiàn)有Android項目集成Flutter Module

現(xiàn)有Android項目集成Flutter Module

點擊查看現(xiàn)有iOS項目集成Flutter Module

點擊查看現(xiàn)有Android項目集成Flutter Module

  • 在現(xiàn)有Android項目同級目錄終端創(chuàng)建flutter module
flutter create -t module --org com.tikeyc flutter_module -i objc -a java
  • 注意事項
    settings.gradle文件
rootProject.name = "FlutterAndroid"
include ':app'
// 增加下面代碼彰亥,Android項目和flutter_module項目在同級目錄時
setBinding(new Binding([gradle: this]))
evaluate(new File(
        settingsDir.parentFile,
        'flutter_module/.android/include_flutter.groovy'
))
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
改為
 /*
    FAIL_ON_PROJECT_REPOS
    表示如果工程單獨設(shè)置了倉庫纪吮,或工程的插件設(shè)置了倉庫匾竿,構(gòu)建就直接報錯拋出異常
    PREFER_PROJECT
    表示如果工程單獨設(shè)置了倉庫,就優(yōu)先使用工程配置的抡医,忽略settings里面的
    PREFER_SETTINGS
    表述任何通過工程單獨設(shè)置或插件設(shè)置的倉庫,都會被忽略
 */
 repositoriesMode.set(RepositoriesMode.PREFER_PROJECT)
否則報錯:
Caused by: org.gradle.api.internal.plugins.PluginApplicationException: Failed to apply plugin class 'FlutterPlugin'.

但是這樣改了以后但校,那么原來setting.gradle下面設(shè)置的全局配置的鏡像就沒用了
解決方式:在主工程目錄下的gradle添加鏡像

allprojects{
        repositories {
            maven { url "https://jitpack.io" }
            maven { url 'https://maven.aliyun.com/nexus/content/repositories/google' }
            maven { url 'https://maven.aliyun.com/repository/public' }
            maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}
            google()
            mavenCentral()
        }
}
  • 主項目添加flutter模塊
    app的build.gradle文件
implementation project(path: ':flutter')
  • 示例代碼
    MyApplication
public class MyApplication extends Application {
    public static final String MY_ENGINE_ID = "my_engine_id";

    public FlutterEngine flutterEngine;

    @Override
    public void onCreate() {
        super.onCreate();

        initFlutterEngine();
    }

    private void initFlutterEngine() {
        // Instantiate a FlutterEngine.
        flutterEngine = new FlutterEngine(this);

        // Configure an initial route.
        flutterEngine.getNavigationChannel().setInitialRoute("/");

        // Start executing Dart code to pre-warm the FlutterEngine.
        flutterEngine.getDartExecutor().executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
        );

        // Cache the FlutterEngine to be used by FlutterActivity.
        FlutterEngineCache
                .getInstance()
                .put(MY_ENGINE_ID, flutterEngine);
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.FlutterAndroid"
        tools:targetApi="31">
        <activity
            android:name=".MyFragmentActivity"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="io.flutter.embedding.android.FlutterActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:theme="@style/Theme.FlutterAndroid"
            android:windowSoftInputMode="adjustResize" />
    </application>

</manifest>

MainActivity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 默認啟動方式
        LinearLayout linearLayout = findViewById(R.id.my_button_super);
        Button button1 = linearLayout.findViewById(R.id.my_button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = FlutterActivity.createDefaultIntent(MainActivity.this);
                startActivity(intent);
            }
        });
        // initialRoute初始化路由
        Button button2 = linearLayout.findViewById(R.id.my_button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = FlutterActivity
                        .withNewEngine()
                        .initialRoute("/")
                        .build(MainActivity.this);
                startActivity(intent);
            }
        });

        // 使用緩存的FlutterEngine炸茧,明顯提高啟動性能
        Button button3 = linearLayout.findViewById(R.id.my_button3);
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = FlutterActivity
                        .withCachedEngine(MyApplication.MY_ENGINE_ID)
                        .build(MainActivity.this);
                startActivity(intent);
            }
        });

        // 打開FlutterFragment
        Button button4 = linearLayout.findViewById(R.id.my_button4);
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyFragmentActivity.class);
                startActivity(intent);
            }
        });

        //
        FlutterView flutterView = new FlutterView(this);

    }
}

MyFragmentActivity

public class MyFragmentActivity extends FragmentActivity {
    // Define a tag String to represent the FlutterFragment within this
    // Activity's FragmentManager. This value can be whatever you'd like.
    private static final String TAG_FLUTTER_FRAGMENT = "flutter_fragment";

    // Declare a local variable to reference the FlutterFragment so that you
    // can forward calls to it later.
    private FlutterFragment flutterFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Inflate a layout that has a container for your FlutterFragment.
        // For this example, assume that a FrameLayout exists with an ID of
        // R.id.fragment_container.
        setContentView(R.layout.activity_my_fragment);

        // Get a reference to the Activity's FragmentManager to add a new
        // FlutterFragment, or find an existing one.
        FragmentManager fragmentManager = getSupportFragmentManager();

        // Attempt to find an existing FlutterFragment,
        // in case this is not the first time that onCreate() was run.
        flutterFragment = (FlutterFragment) fragmentManager
                .findFragmentByTag(TAG_FLUTTER_FRAGMENT);

        // Create and attach a FlutterFragment if one does not exist.
        if (flutterFragment == null) {
//            flutterFragment = FlutterFragment.createDefault();
//            flutterFragment = FlutterFragment
//                    .withNewEngine()
////                    .dartEntrypoint()
//                    .initialRoute("/")
//                    .build();
            flutterFragment = FlutterFragment
                    .withCachedEngine(MyApplication.MY_ENGINE_ID)
//                    .shouldAttachEngineToActivity(false) // 以免 Flutter 控制 Activity 的系統(tǒng) UI,可以使用 FlutterFragment 的 Builder 中的 shouldAttachEngineToActivity() 方法
                    .build();

            fragmentManager
                    .beginTransaction()
                    .add(R.id.fragment_container, flutterFragment, TAG_FLUTTER_FRAGMENT)
                    .commit();
        }
    }

    @Override
    public void onPostResume() {
        super.onPostResume();
        flutterFragment.onPostResume();
    }

    @Override
    protected void onNewIntent(@NonNull Intent intent) {
        super.onNewIntent(intent);
        flutterFragment.onNewIntent(intent);
    }

    @Override
    public void onBackPressed() {
        flutterFragment.onBackPressed();
    }

    @Override
    public void onRequestPermissionsResult(
            int requestCode,
            @NonNull String[] permissions,
            @NonNull int[] grantResults
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        flutterFragment.onRequestPermissionsResult(
                requestCode,
                permissions,
                grantResults
        );
    }

    @Override
    public void onUserLeaveHint() {
        flutterFragment.onUserLeaveHint();
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        flutterFragment.onTrimMemory(level);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扔罪,一起剝皮案震驚了整個濱河市秉沼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矿酵,老刑警劉巖唬复,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異全肮,居然都是意外死亡敞咧,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門辜腺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來休建,“玉大人乍恐,你說我怎么就攤上這事〔馍埃” “怎么了茵烈?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長砌些。 經(jīng)常有香客問我呜投,道長,這世上最難降的妖魔是什么存璃? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任仑荐,我火速辦了婚禮,結(jié)果婚禮上纵东,老公的妹妹穿的比我還像新娘粘招。我一直安慰自己,他們只是感情好偎球,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布洒扎。 她就那樣靜靜地躺著,像睡著了一般甜橱。 火紅的嫁衣襯著肌膚如雪逊笆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天岂傲,我揣著相機與錄音难裆,去河邊找鬼。 笑死镊掖,一個胖子當(dāng)著我的面吹牛乃戈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亩进,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼症虑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了归薛?” 一聲冷哼從身側(cè)響起谍憔,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎主籍,沒想到半個月后习贫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡千元,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年苫昌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幸海。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡祟身,死狀恐怖奥务,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情袜硫,我是刑警寧澤氯葬,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站父款,受9級特大地震影響溢谤,放射性物質(zhì)發(fā)生泄漏瞻凤。R本人自食惡果不足惜憨攒,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阀参。 院中可真熱鬧肝集,春花似錦、人聲如沸蛛壳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衙荐。三九已至捞挥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間忧吟,已是汗流浹背砌函。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溜族,地道東北人讹俊。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像煌抒,于是被迫代替她去往敵國和親仍劈。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容