Android Cordova微信插件动态包名处理

问题描述

在使用微信开放平台(https://open.weixin.qq.com/)开发插件的时候,遇到项目中的WXActivity和WXPayEntryActivity必须在Activity符合如下规范配置:

项目包名.wxapi.WXEntryActivity

项目包名.wxapi.WXPayEntryActivity

简单示例如下:

<activity
    android:name=".wxapi.WXEntryActivity"
    android:label="@string/launcher_name"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="$WECHATAPPID"/>
    </intent-filter>
</activity>
<activity
    android:name=".wxapi.WXPayEntryActivity"
    android:label="@string/launcher_name"
    android:exported="true"
    android:launchMode="singleTop">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="$WECHATAPPID"/>
    </intent-filter>
</activity>

通常意义上,如果我们制作的插件只使用一次的话,我们可以将以上两个类的包名写死,但是考虑到插件的通用性,这种方式肯定是有问题的。

 

解决方法一:使用activity-alias

activity-alias是给Activity一个别名,同样的,如果通过别名访问真实的Activity,那么也会自动关联到真实的activity,具体配cordova plugin.xml如下。

注意:

① activity-alias使用android:targetActivity链接到真实的acitivity

② activity-alias中的配置和同样也会传递给真实的activity

③ 通过activity-alias调用activity和直接调用activity时,activity-alias可以传递配置给activity,但不能更改原有的配置,因此,直接调用时,安装真实的配置启动Activity。

<config-file target="AndroidManifest.xml" parent="/manifest/application">
<!-- 真实activity -->   
<activity android:name="cn.xu.li.cordova.wechat.WXEntryActivity" 
         android:screenOrientation="portrait" 
         android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
    <activity android:name="cn.xu.li.cordova.wechat.WXPayEntryActivity" 
        android:screenOrientation="portrait" 
        android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
<!-- 别名activity -->  
    <activity-alias android:name=".wxapi.WXEntryActivity"
        android:targetActivity="cn.xu.li.cordova.wechat.WXEntryActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
             <data android:scheme="$WECHAT_APPID"/>
        </intent-filter>
    </activity-alias>
     <activity-alias android:name=".wxapi.WXPayEntryActivity"
         android:targetActivity="cn.xu.li.cordova.wechat.WXPayEntryActivity" 
         android:exported="true"
         android:launchMode="singleTop"
         >
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
             <data android:scheme="$WECHAT_APPID"/>
        </intent-filter>
    </activity-alias>

</config-file>

 

解决方法二:使用Cordova Hooks

Cordova插件开发过程中,因为核心是plugin.xml的配置,我们既可以使用自动化构建工具,也可以不使用。但是,在解决某些特殊的问题时,使用自动化构建工具可以给我们很方便的解决这些问题。

Cordova Hooks支持很多语言,其中nodejs是比较主流的自动化构建语言,这里的脚本是以nodejs开发的。

 

配置plugin.xml如下:

<platform name="android">
        <hook type="after_plugin_add" src="scripts/android-install.js" />
        <hook type="after_plugin_install" src="scripts/android-install.js" />
        <hook type="before_plugin_rm" src="scripts/android-install.js" />
        <hook type="before_plugin_uninstall" src="scripts/android-install.js" />

<config-file target="AndroidManifest.xml" parent="/manifest/application">
    <activity
        android:name=".wxapi.WXEntryActivity"
        android:label="@string/launcher_name"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:scheme="$WECHATAPPID"/>
        </intent-filter>
    </activity>
    <activity
        android:name=".wxapi.WXPayEntryActivity"
        android:label="@string/launcher_name"
        android:exported="true"
        android:launchMode="singleTop">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:scheme="$WECHATAPPID"/>
        </intent-filter>
    </activity>
</config-file>

<!-- 此处省略掉与本问题毫无关联的配置 -->

</platform>

两个Acitivity包名配置如下:

package __PACKAGE_NAME__;

脚本如下:

#!/usr/bin/env node

module.exports = function (context) {
    var path        = context.requireCordovaModule('path'),
        fs          = context.requireCordovaModule('fs'),
        shell       = context.requireCordovaModule('shelljs'),
        projectRoot = context.opts.projectRoot,
        plugins     = context.opts.plugins || [];

    // 判断调用此脚本时加载或者卸载的插件是否是当前微信插件
    if (plugins.length > 0 && plugins.indexOf('cordova-plugin-wechat') === -1) {
        return ;
    }

    var ConfigParser = null;
    try {
        ConfigParser = context.requireCordovaModule('cordova-common').ConfigParser;
    } catch(e) {
        // fallback
        ConfigParser = context.requireCordovaModule('cordova-lib/src/configparser/ConfigParser');
    }

    var config      = new ConfigParser(path.join(context.opts.projectRoot, "config.xml")),
        packageName = config.android_packageName() || config.packageName();//获取包名

    // replace dash (-) with underscore (_)
    packageName = packageName.replace(/-/g , "_"); 
    
    console.info("Running android-install.Hook: " + context.hook + ", Package: " + packageName + ", Path: " + projectRoot + ".");

    if (!packageName) {
        console.error("Package name could not be found!");
        return ;
    }
//判断是否是android插件,否则不需要执行此插件
    if (context.opts.cordova.platforms.indexOf("android") === -1) {
        console.info("Android platform has not been added.");
        return ;
    }
//获取要生成WXActivity和WXPayEntry的目录
    var targetDir  = path.join(projectRoot, "platforms", "android", "src", packageName.replace(/\./g, path.sep), "wxapi");
        targetFiles = ["EntryActivity.java", "WXEntryActivity.java", "WXPayEntryActivity.java"];

//如果卸载插件时,删除原有的Activity
    if (['after_plugin_add', 'after_plugin_install'].indexOf(context.hook) === -1) {
        // remove it?
        targetFiles.forEach(function (f) {
            try {
                fs.unlinkSync(path.join(targetDir, f));
            } catch (err) {}
        });
    } else {
        // create directory
        shell.mkdir('-p', targetDir);

        // sync the content
        targetFiles.forEach(function (f) {
            fs.readFile(path.join(context.opts.plugin.dir, 'src', 'android', f), {encoding: 'utf-8'}, function (err, data) {
                if (err) {
                    throw err;
                }
//替换包名
                data = data.replace(/^package __PACKAGE_NAME__;/m, 'package ' + packageName + '.wxapi;');
//将两个activity写入到指定的目录
                fs.writeFileSync(path.join(targetDir, f), data);
            });
        });
    }
};

 

参考:

Android activity-alias 多入口配置

activity-alias详解及应用

转载于:https://my.oschina.net/ososchina/blog/1599835

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值