uniapp主屏继承WebappActivity并实现跳转原生页面

背景

项目需要,想在uniapp页面内通过一个点击事件跳转到安卓原生页面。百度没找到解决办法。

分析

  1. 要实现跳转原生必须要得到Activity的控制权,就是要继承框架二次封装的Activity基类。
  2. 有了Activity控制权后需要在uniapp通过js拿到Activity的实例。
  3. 有了实例后再通过自定义方法跳转Activity。

资料

  1. 自定义Activity继承PandoraEntryActivity
    • 这里还有一个细节需要手动处理:uniapp的启动流程是先进入PandoraEntry,再到PandoraEntryActivity的,这里PandoraEntry跳转的页面默认是PandoraEntryActivity,所以我们需要自定义一个入口让他跳转到我们自己的MainActivity
    • 自定义的Entry入口类中需要传入一个__start_from_to_class__的intent参数才能让PandoraEntry跳转到自定义的主活动页。
    • 不建议在自定义的Entry类中直接跳转MainActivity,因为PandoraEntry可能有一些初始化动作。
  2. plus.android.runtimeMainActivity()可以直接拿到当前的Activity实例,uniapp页面中一般都只在主活动中,很少跳转到其他活动。
  3. 安卓原生通过Intent可以实现页面跳转。

完整代码

// 新的入口
package com.xxx.xx;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

import io.dcloud.PandoraEntry;

public class Entry extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = this.getIntent();
        // 自定义的入口
        intent.putExtra("__start_from_to_class__", MainActivity.class.getName());
        // 进入uniapp自带入口
        intent.setClass(this, PandoraEntry.class);
        this.startActivity(intent);
    }
}
// 自定义MainActivity,以后uniapp就在这个页面渲染
package com.xxx.xx;

import io.dcloud.PandoraEntryActivity;

import android.content.Intent;
import android.os.Bundle;

public class MainActivity extends PandoraEntryActivity {

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
    }

    /**
     * 跳转原生页面
     */
    public void testActivity() {
        Intent intent = new Intent(MainActivity.this, TestActivity.class);
        startActivity(intent);
    }
}

manifest也要修改,相关保密字串用xxx代替:

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

    <uses-sdk tools:overrideLibrary="com.bun.miitmdid" />

    <uses-permission
        android:name="android.permission.INSTALL_PACKAGES"
        tools:ignore="ProtectedPermissions" />
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.xxx">
        <meta-data
            android:name="dcloud_appkey"
            android:value="xxx" />
        <!-- 新的Activity -->
        <activity android:name=".TestActivity" />
        <!-- 原来的 io.dcloud.PandoraEntry -->
        <activity
            android:name=".Entry"
            android:configChanges="orientation|keyboardHidden|keyboard|navigation"
            android:hardwareAccelerated="true"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:screenOrientation="user"
            android:theme="@style/TranslucentTheme"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!--删除原来 io.dcloud.PandoraEntry 的intent-filter -->
        <activity android:name="io.dcloud.PandoraEntry"
            android:configChanges="orientation|keyboardHidden|keyboard|navigation"
            android:hardwareAccelerated="true"
            android:launchMode="singleTask"
            android:screenOrientation="user"
            android:theme="@style/TranslucentTheme"
            android:windowSoftInputMode="adjustResize" />

        <!-- 原来的io.dcloud.PandoraEntryActivity -->
        <activity
            android:name=".MainActivity"
            android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale|keyboard|smallestScreenSize|screenLayout|screenSize"
            android:hardwareAccelerated="true"
            android:launchMode="singleTask"
            android:permission="com.miui.securitycenter.permission.AppPermissionsEditor"
            android:screenOrientation="user"
            android:theme="@style/DCloudTheme"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <action android:name="android.intent.action.VIEW" />
                <data android:scheme="xxx" />
            </intent-filter>
        </activity>

        <provider
            android:name="io.dcloud.common.util.DCloud_FileProvider"
            android:authorities="com.xxx.xx.dc.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/dcloud_file_provider" />
        </provider>
    </application>

</manifest>

uniapp中:

let bundle = plus.android.runtimeMainActivity();
bundle.testActivity();

踩坑

  1. 如果需要调试原生页面的话,肯定需要直接运行到手机的,但是每次直接运行打开都会提示未配置appkey或配置错误导致进不了应用。这个问题其实是因为Android Studio直接运行的时候会以debug运行,就是免签名运行,这样会使uniapp框架识别不到我们配置的appid,所以会出现上述问题。解决办法很简单:

    // gradle中配置
    
    signingConfigs {
    	debug {
    		// 填你的签名文件路径
        	storeFile file('xx/xx/xx.jks')
            storePassword 'xxx'
            keyAlias 'xxx'
            keyPassword 'xxx'
            v1SigningEnabled true
            v2SigningEnabled true
        }
    }
    // 或者Android Studio中设置:
    // File->Project Stucture->Modules->Signing Configs
    // 选debug按提示填资料即可
    // 设置完后记得gradle补充两个参数v1SigningEnabled、v2SigningEnabled
    
    // 又或者在最左侧工具栏里选Build Variants,在Active Build Variant中选择release,让调试也按发布版本的配置运行。这个方法可能在运行的时候会报错,暂时不知道什么原因。
    
    // 配置好后直接运行就可以了
  2. 不要尝试通过配置uniapp框架来跳过appkey验证,我没有发现更好的uniapp配置办法。

  3. 2022-02-09后续,单独继承跳转不可靠,在退出应用时会回到第一屏,这时候的第一屏是无ui状态,会黑屏,需要另寻方案。


uniapp主屏继承WebappActivity并实现跳转原生页面
http://blog.icy8.cn/posts/23303/
作者
icy8
发布于
2022年1月18日
许可协议