最近开发项目需要在Unity上使用QQ授权登录,因为Unity不能直接去做这个,官方也没有提供这样的插件,虽然ShareSDK提供了Unity的插件,但是个人感觉用起来比较臃肿,所以决定使用原生Android开发一个插件(arr)供Unity使用。
百度了一下网上有很多这种案例,但是发现他们有一个共同的缺点就是直接去修改Android Studio创建好的项目结构,一是麻烦,二是稍微有一个地方没改对,就会报错,个人感觉不太方便。
那么今天咱们使用另一种方法去做,let’s go…
打包好的插件(arr包)下载地址:QQ授权插件(arr包)
进入正题:
Andoird部分
-
首先新建一个在正常不过的Android Studio项目(这里不拿主项目做修改,向下看)
知识点:项目依赖下载慢的解决方法,使用阿里云的maven库,在项目根目录下的build.gradle配置:buildscript { repositories { maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'} maven { url "https://jitpack.io" } google() } dependencies { classpath 'com.android.tools.build:gradle:3.5.2' } } allprojects { repositories { maven{url 'http://maven.aliyun.com/nexus/content/groups/public/'} google() } } task clean(type: Delete) { delete rootProject.buildDir }
-
右击项目,选择New->Module,选择Android Library,单击下一步
-
输入Module name,可以根据需要修改一下Package name,单击完成
-
在main文件夹下新建一个res文件夹,在res目录下文件一个values文件夹,在values文件夹下新建一个strings.xml文件,在strings.xml文件中配置
<resources> <string name="app_name">科技馆访客端</string> </resources>
如图所示:
-
如果需要jar包,就将jar包放在libs文件夹中,然后在build.gradle(注意这个文件不是项目根目录下的)文件中配置一下jar包,这里我使用的是Unity的classes.jar包和QQ授权的jar包
api fileTree(dir: 'libs', include: 'classes.jar') api fileTree(dir: 'libs', include: 'open_sdk_r8353806.jar')
如图所示:
知识点:D:\Install\Unity2018.4.12f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes -
新建一个MainActivity.java文件(名字随便起),继承UnityPlayerActivity,然后写方法供Unity调用即可,下面拿QQ授权示例:
import android.content.Intent; import android.widget.Toast; import androidx.annotation.Nullable; import com.tencent.connect.common.Constants; import com.tencent.tauth.IUiListener; import com.tencent.tauth.Tencent; import com.tencent.tauth.UiError; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; public class MainActivity extends UnityPlayerActivity { /** * 腾讯类 */ private Tencent tencent; /** * 授权回调 */ private IUiListener listener; /** * QQ初始化 */ public void qqInit(String appId){ tencent = Tencent.createInstance(appId, this.getApplicationContext()); listener = new IUiListener() { @Override public void onComplete(Object o) { UnityPlayer.UnitySendMessage("Authorize","OnComplete",o.toString()); } @Override public void onError(UiError uiError) { UnityPlayer.UnitySendMessage("Authorize","OnError",uiError.errorCode+"-"+uiError.errorMessage+"-"+uiError.errorDetail); } @Override public void onCancel() { UnityPlayer.UnitySendMessage("Authorize","OnCancel","取消授权"); } }; } /** * QQ登录 */ public void getQQCode(String appId) { tencent = Tencent.createInstance(appId, this.getApplicationContext()); if (!tencent.isSessionValid()) { tencent.login(this, "all", listener); } } /** * 必须加这个才能回调 * @param requestCode * @param resultCode * @param data */ @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (requestCode == Constants.REQUEST_LOGIN) { Tencent.onActivityResultData(requestCode, resultCode, data, listener); super.onActivityResult(requestCode, resultCode, data); } } /** * 原生弹框 * @param msg */ public void showToast(final String msg) { runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } }); } }
-
配置AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.test"> <!-- 这里的包名一定要和unity中的一致 --> <!-- 这里是授权 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <application android:label="@string/app_name"> <!-- 这里是App的名字,获取的strings.xml配置文件中的 --> <!-- QQ授权必须要加的 --> <uses-library android:name="org.apache.http.legacy" android:required="false" /> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <!-- Unity使用必须要加的 --> <meta-data android:name="unityplayer.UnityActivity" android:value="true"/> </activity> <!-- 下面两个activity的配置是QQ授权官方的 --> <activity android:name="com.tencent.tauth.AuthActivity" android:noHistory="true" android:launchMode="singleTask" > <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="1106617541" /> </intent-filter> </activity> <activity android:name="com.tencent.connect.common.AssistActivity" android:configChanges="orientation|keyboardHidden" android:screenOrientation="behind" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> </application> </manifest>
-
打包,选择Build->Make Project,生成arr包
-
最后一点要注意的就是,将arr包给Unity使用前要使用压缩文件打开压缩包,将libs文件夹下的classes.jar文件删掉,至此Unity的Android插件制作完毕,接下来是Unity调用部分
-
别忘了将android的 AndroidManifest.xml 文件也放在Unity中,和 classes.jar 放一块,路径为:
Assets/Plugins/Android
Unity部分
1、利用反射机制获取到Android原生类
AndroidJavaClass ajc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject ajo = ajc.GetStatic<AndroidJavaObject>("currentActivity");
2、调用方法
1)、无参数无返回值
ajo.Call("test"); //test :安卓的方法名
2)、无参数有返回值
ajo.Call<string>("test");
3)、有单个参数无返回值
ajo.Call("test","参数1");
4)、有多个参数无返回值
ajo.Call("test",new object[]{"参数1","参数2"});
ajo.Call("test","参数1","参数2");
5)、有多个参数有返回值
ajo.Call<string>("test","参数2","参数2");
2022-01-18补充
新版 Unity 在 classes.jar 中没有了 UnityPlayerActivity.java 文件,它将这个文件单独提出来放在了如下文件夹目录:
D:\Install\Unity2018.4.12f1\Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player
直接将 UnityPlayerActivity.java 文件复制到 Android 项目中即可,如图:
最后在 Unity 中打 Android 包的时候报错如下图:
解决方法:
把自己unity文件目录D:\Install\Unity2018.4.12f1\Editor\Data\PlaybackEngines\AndroidPlayer\Source下的文件夹删掉即可