Unity发布Android平台实现网页打开应用并传参
在之前的Windows平台网页拉起应用会有很多问题需要解决,在安卓平台就不会有那么多问题了。
但是该有的拉起应用的协议还是要有的,本篇文章主要讲安卓平台的网页拉起应用并传参。
一、还是自定义协议,只不过在安卓平台不是写入数据到注册表了,而且开发过程中,直接把协议,写入到manifest.xml文件中。并且需要打开一个权限,打开的权限如下(最后会贴上完整的xml文件)
<!--需要被网页拉起必须设置-->
<category android:name="android.intent.category.BROWSABLE" />
Unity中自定义manifest.xml文件,需要在Project Settings=>Player=>Android=>Publishing Settings=>Custom Main Manifest勾选上,那么在Plugins文件夹下会生成一个manifest.xml文件,就可以直接在内部修改了。
协议部分,URL Scheme协议格式:
一个完整的完整的URL Scheme协议格式由scheme、host、port、path和query组成,其结构如下所示:
<scheme>://<host>:<port>/<path>?<query>//例如 metaversebeta://metaverse:9092/product?productId=10000007
metaversebeta: 即Scheme 该Scheme协议名称(必填)
metaverse: 即Host,代表Scheme作用于哪个地址域(必填)
9092: 即port,代表端口号(必填)
product:即path,代表打开的页面
param: 即query,代表传递的参数
在manifest.xml文件中,scheme对应windows一样的协议,但是安卓平台还必须增加host和port,有部分博主提供的host还是port可以不写,可能旧版本的可以,但是现在版本中 scheme、host、port都必填,少一个就没办法拉起应用,浏览器中也要对应填写这三个。
<!--协议部分-->
<data android:scheme="metaversebeta"android:host="metaverse"android:port="9092"
如果完整的在xml和浏览器中都填写了相同的协议,那么浏览器点击按钮后就能在安卓端正常打开应用了,需要注意的是,正常安卓端应用,不会出现多开的情况,所以拉起的应用,如果没打开,就打开应用,如果已经打开了,那么拉起的是打开的应用,但是现在很多安卓机都会有分身的情况,就不清楚会不会有问题(我也没测试过),如果有朋友碰到了,可以帮忙评论区更新哈。非常感谢~
二、传参
上面讲协议的时候已经说了浏览器怎么传参了,就是问好后面的都是参数,自行去定义怎么拼接,解析就行。一般情况,都会key1=value1&key2=value2因为这个规则是符合浏览器路由的规则,一般不会出问题,如果是其他规则说不定会有问题。
三、Unity层获取参数
在安卓端Unity层没法直接获取网页传过来的参数,必须通过安卓的Java编写代码获取。因为新版本Unity能识别java脚本了,所以过去参数这种简单的java代码,不需要通过Android Studio去编写arr库了。
直接在Plugins文件夹下创建个txt,重命名为MainActivity.java即可,文件名也可以自行定义,但是后缀必须是java。下面直接上参考代码,可以根据自己项目定义参数修改
package com.unity3d.player;import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;public class MainActivity extends UnityPlayerActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState); }public String GetSchemeQueryRoomId(){Intent intent = getIntent();String scheme = intent.getScheme();String dataString = intent.getDataString();Uri uri = intent.getData();String info="";if (uri != null) {//完整的url信息String url = uri.toString();//scheme部分String schemes = uri.getScheme();//host部分String host = uri.getHost();//port部分int port = uri.getPort();//访问路径String path = uri.getPath();//编码路径String path1 = uri.getEncodedPath();//query部分String queryString = uri.getQuery();//获取参数值info=uri.getQueryParameter("roomid"); //info=url; }return info;}public String GetSchemeQueryRandom(){Intent intent = getIntent();String scheme = intent.getScheme();String dataString = intent.getDataString();Uri uri = intent.getData();String info="没数据";if (uri != null) {//完整的url信息String url = uri.toString();//scheme部分String schemes = uri.getScheme();//host部分String host = uri.getHost();//port部分int port = uri.getPort();//访问路径String path = uri.getPath();//编码路径String path1 = uri.getEncodedPath();//query部分String queryString = uri.getQuery();//获取参数值info=uri.getQueryParameter("random"); //info=url; }return info;}public String GetSchemeUrl(){Intent intent = getIntent();String scheme = intent.getScheme();String dataString = intent.getDataString();Uri uri = intent.getData();String info="没数据";if (uri != null) {//完整的url信息String url = uri.toString();//scheme部分String schemes = uri.getScheme();//host部分String host = uri.getHost();//port部分int port = uri.getPort();//访问路径String path = uri.getPath();//编码路径String path1 = uri.getEncodedPath();//query部分String queryString = uri.getQuery();//获取参数值//info=uri.getQueryParameter(key); info=url; }return info;}public String getData(){return "testcontent";}
}
需要注意的是该脚本继承的是UnityPlayerActivity,一个安卓应用只能有唯一的一个Activity,所以我们需要在manifest.xml中UnityPlayerActivity改成继承了他的子类也就是MainActivity,这样打开应用的时候就会自动生成对应的实列,否则该java类的实例没生成,就会没法调用获取信息。当然如果会java的,不继承UnityPlayerActivity,另外编写一个类,去实例化,获取信息也可以。
到此需要修改manifest.xml文件的内容就完成了,下面直接放上完整的xml文件内容。
<?xml version="1.0" encoding="utf-8"?>
<!-- GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN-->
<manifestxmlns:android="http://schemas.android.com/apk/res/android"package="com.unity3d.player"xmlns:tools="http://schemas.android.com/tools"><application android:usesCleartextTraffic="true"><activity android:name="com.unity3d.player.MainActivity"android:theme="@style/UnityThemeSelector"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter><!--必须设置--><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><!--需要被网页拉起必须设置--><category android:name="android.intent.category.BROWSABLE" /><!--协议部分--><data android:scheme="metaversebeta"android:host="metaverse"android:port="9092"/></intent-filter><meta-data android:name="unityplayer.UnityActivity" android:value="true" /></activity></application>
</manifest>
接下去是Unity层调用Java脚本获取参数,这部分也比较简单,已经有很多内容编写怎么调用java脚本了。因此我这边就实际放上参考代码,根据自己项目实际情况修改
public string GetScheme(SchemeType type){AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");switch (type){case SchemeType.RoomID:return jo.Call<string>("GetSchemeQueryRoomId");case SchemeType.RandomID:return jo.Call<string>("GetSchemeQueryRandom");default:return jo.Call<string>("GetSchemeUrl");}}
到此安卓端网页拉起应用并传参已经结束了,完全对应实现,就能正常拉起应用并且获取到信息了。
最后有个小问题,做个提示,不提示实际完成测试的时候也会发现。
Unity层去调用GetScheme获取网页层传过来的数据,每次调用获取的都是上一次网页传输的数据,为了确保拿到的是新的数据,两种处理方式,
第一种:java层调用获取到数据后,去清除数据。
第二种:传的参数增加一个随机变量,通过该变量判断数据是否有更新,因为时候传参的可能是一样的,但是需要再次那这个参数进行对应的业务逻辑。