我看到过很多unity接sdk的方式,但是主要分为两种
1.以unity工程为主,导入sdk的jar包和修改配置AndroidManifest.xml,这种方式优点就是不脱离unity,但是这样接sdk的资料太少,而且如果sdk过多不方便。
2.我今天主要说第二种方式,导出Android工程在esplise里进行接入并且进行二次开发,因为第二种方式需要对esplise和java有一定程度的了解,对我而言第二种方式更适合长期的投资。今天我就把我这三个月学习经验向大家分享一下。
因为今天这篇文章涉及的不仅仅是unity,大体的东西我就都说一下,如果有疑问的地方可以留言或者自己找资料。
一.要做sdk接入首先要知道,unity是如何与Android通信的,这个知识点网上有很多,我在这里就举一个简单的例子(补充已经这个脚本是要挂到场景内部的)
这里一共两句代码,先解释第一句代码,这句代码无非是找到esplise里com.example.testcommunicate下的PlatformContext类
第二句代码留个悬念,然后再unity内部留出测试接口
二.进行esplise内部接口的实现,也就是unity与Android通信的第二步。说到这里呢,com.example.testcommunicate.PlatformContext就能用上了。
这就是我esplise的目录结构,多余的脚本会后续解释。第一步我们已经确定了Android内部的通信类PlatformContext,我们来实现它内部的通信接口。
通常来说这个PlatformContext我们都定义为抽象类,方便以后开发,我先给出抽象类,再给出实现的子类
package com.example.testcommunicate;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import com.unity3d.player.UnityPlayer;
public abstract class PlatformContext {
protected static PlatformContext m_instance;
private Context m_ctx;
private Activity m_activity;
protected String m_target;
protected JSONObject m_config;
protected String m_tag;
protected String m_userId;
protected String m_nickname;
protected String m_channelUserInfo;
protected String m_channelSid;
protected String m_orderUrl;
protected String m_devilerUrl;
protected String m_imei;
protected String m_pkgid;
protected String m_packageName;
protected String m_version;
protected String m_serverId;
protected String m_serverName;
protected abstract void initContext(String config);
public abstract boolean destroyContext();
public abstract void login(int nParam);
public abstract void logout();
public abstract void switchAccount();
public abstract boolean isLogin();
protected abstract String getSession();
protected abstract String getGameId();
public static PlatformContext getInstance()
{
return m_instance;
}
protected void setGameObject(String name) {
m_target = name;
}
protected PlatformContext(String tag)
{
m_instance = this;
m_activity = UnityPlayer.currentActivity;
m_ctx = m_activity.getApplicationContext();
m_pkgid = m_activity.getClass().getPackage().getName();
m_packageName = m_activity.getPackageName();
try {
m_version = m_activity.getPackageManager().getPackageInfo(m_packageName, 0).versionName;
} catch (Exception e) {
m_version = "0";
}
}
protected PlatformContext(String target,String tag)
{
m_instance = this;
m_activity = UnityPlayer.currentActivity;
m_ctx = m_activity.getApplicationContext();
m_pkgid = m_activity.getClass().getPackage().getName();
m_packageName = m_activity.getPackageName();
try {
m_version = m_activity.getPackageManager().getPackageInfo(m_packageName, 0).versionName;
} catch (Exception e) {
m_version = "0";
}
}
}
package com.example.testcommunicate;
import java.util.HashMap;
import android.util.Log;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Handler;
import android.os.Looper;
import com.unity3d.player.UnityPlayer;
public class TSPlatformContext extends PlatformContext {
int m_cpId;
int m_gameId;
boolean m_debug = false;
boolean m_blogin;
boolean m_enableGameAccount = false;
String m_gameAccountTitle;
String m_channalID;
String m_uid;
String m_name;
String Timestamp;
String m_token;
//String m_channelID;
String rsa = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArSULL4MRYI8wxLDLCWxQRXiEx61E7Dm9cbMHHY2l3lb3Axi0VEuLI/9Ee0zYF2/jXBfnE1mZAd2pnMHcyOT5yS76uqDQrMRRPUYrTV1zzRPK7pBbGwKdpWWlEwYXEdBvZrQaJQdF9NPBx/KluKs6s0wV2OhU+sRGqW2ohlfNvaL0ji5OOsBeG2d6uRkY7Zh+ZWNJuD/W3zMOb6d13FDsfKPtXpxe6lhZewH/jJz9w925z2HBG9hfjs7gOeIzsCJZS3kYEpeFTWPIGY4FFhRd3Vr3xwhPqyf945+cn43S+o0ZhTabVRwuG5Apk0gWMc8BimnL82GBEz0HzUOyvgydEwIDAQAB";
String roleId = null;
String roleName = null;
String roleLevel;
String zoneId ;
String zoneName = null;
String balance ;
String vip ;
String partyName = null;
public static int tempTypeGame = 1;
public TSPlatformContext(String target) {
super(target,"KZ");
m_blogin = false;
}
public static void Init()
{
if(m_instance==null) {
TSPlatformContext ucctx = new TSPlatformContext("");
ucctx.initPlatform();
}
return;
}
protected void initPlatform() {
// TODO Auto-generated method stub
Log.d("", "initPlatform...");
}
public void initContext(String config) {
Log.d("", "initContext config:"+config);
UnityPlayer.UnitySendMessage("PlatformHelper", "AtoUnity", "sucess");//这个其实就是Android向unity内的反向通信,"PlatformHelper"是unity场景内挂着AndroidTestCommunication的物体名称
}
@Override
public boolean destroyContext() {
// TODO Auto-generated method stub
Log.d("", "destroyContext...");
return false;
}
@Override
public void login(int nParam) {
Log.d("", "login...");
}
@Override
public void logout() {
Log.d("", "logout...");
}
@Override
public void switchAccount() {
Log.d("", "switchAccount...");
}
@Override
public boolean isLogin() {
// TODO Auto-generated method stub
return false;
}
@Override
protected String getSession() {
// TODO Auto-generated method stub
return "";
}
@Override
protected String getGameId() {
// TODO Auto-generated method stub
return "";
}
}
unity内部的完成demo代码
using UnityEngine;
using System.Collections;
public class AndroidTestCommunication : MonoBehaviour
{
AndroidJavaObject m_sdkobj;
// Use this for initialization
AndroidJavaObject klass;
void Awake ()
{
#if NORMAL
#else
// Debug.LogError("AndroidJavaObject Init");
klass = new AndroidJavaClass("com.example.testcommunicate.PlatformContext");
m_sdkobj = klass.CallStatic<AndroidJavaObject>("getInstance");//这句就是通过一个简单的单例获取Android内部的PlatformContext类的实例对象
/// m_sdkobj.Call("setGameObject", name);
#endif
//Debug.LogError(klass);
//Debug.LogError(m_sdkobj);
}
//这里我添加了开机动画很简单的
IEnumerator Start()
{
Debug.LogError("Start");
if (Handheld.PlayFullScreenMovie("Heroes_Kingdom_ingame1280.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput))
yield return new WaitForEndOfFrame();
yield break;
}
// Update is called once per frame
void Update () {
}
void OnGUI()
{
if (GUILayout.Button("button1",GUILayout.Height(Screen.height*0.4f),GUILayout.Width(Screen.height*0.4f)))
{
Debug.LogError("onclick button1");
m_sdkobj.Call("initContext", "success");
}
}
public void AtoUnity(string succes)
{
Debug.LogError("come back:" + succes);
}
}
这里也看到了,我只是实现了一个初始化通信接口
initContext,其实如果接第三方sdk,登录支付接口实现的都是一个道理。
上面把通信说了,可是是怎么个二次开发的呢,其实很简单首先导出unity的esplise包,3个地方
导出后的工程文件夹,将assert下的bin文件和文件拷到新建的Android工程assert文件夹中。还有lib文件夹下的.so文件也同样拷到Android工程的lib文件夹下
然后就是进行esplise内Android工程的修改了,第一步Android工程内lib文件夹下引用
下面这个红色的代码是现成的,在unity里有直接拷贝过来就可以了
最后一步就是进行的修改,我这里给一个通用版,需要修改的地方会标注
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testcommunicate"//这里也是包名对应
android:versionCode="1"
android:versionName="1.0" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity android:label="@string/app_name" android:screenOrientation="sensorLandscape" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:name="com.example.testcommunicate.UnityPlayerNativeActivity">//这里要和你自己的包名对应上
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity>
</application>
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-feature android:name="android.hardware.sensor.accelerometer" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
</manifest>
需要改的地方都好了,剩下就是出包测试了。刚开始写文章,感觉思路优点混乱,可以随时纠正一起学习。