由于我刚刚学习Unity3d,所以打算写一款手游,但在账号密码输入界面,我发现了一个问题,当用户点击登陆时,如果输入框没值,那么我想告诉用户你必须要输入值,这在android中很常见,因为Android只需要一行代码即可完成
Toast.makeText(getApplicationContext(), "is Toast",Toast.LENGTH_SHORT).show();
但是当我天真的去翻Unity时并没有找到相应的c#代码。
所以我疯狂的百度博客,有不少博客也写到了Unity和Android之间互相调用,但是我尝试了很多博客,发现这些博客总共就2种方法,
第一种:将android代码打包成jar,arr文件放到Unity工程。
第二种将Unity工程导成Android项目在做修改。
但这两种方法无疑都是很麻烦的,在我尝试的过程中发生了大量问题,我足足修改了2天,才将arr文件顺利打包进unity的apk文件,但是使用过程中我发现android报错了,通过翻遍apk的源码,我发现这个错误是说Jni找不到你定义的方法,通过Log的查询我发现它在UnityActivity中寻找,而这个类中是并没有存在这个方法的,为此我想了好久,不断的测试,都没找到方法。
为此我询问了我朋友,他和我一起寻找,终于在GitHub上找到了一个解决方法,其实我们不需要去定义jar包或者arr文件,因为当unity打包的时候会自动导入andorid类,并且将c#代码转换成java代码
因此我们只要通过Unity定义的方法获取android的类,进行方法调用即可,不需要自己去开个android项目
接下来,我会将代码和网站放上来,帮助和我一样踩坑的人
网站:https://github.com/mtsalenc/toaster
Unity脚本代码
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class ShowToast : MonoBehaviour {
string toastString;
string input;
AndroidJavaObject currentActivity;
AndroidJavaClass UnityPlayer;
AndroidJavaObject context;
// Use this for initialization
void Start () {
if (Application.platform == RuntimePlatform.Android) {
UnityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
currentActivity = UnityPlayer.GetStatic<AndroidJavaObject> ("currentActivity");
context = currentActivity.Call<AndroidJavaObject> ("getApplicationContext");
}
}
public void ToAndroidClipBoard(string s){
//InputField txtField){
if (Application.platform == RuntimePlatform.Android) {
//input = txtField.text;
input=s;
currentActivity.Call("runOnUiThread",new AndroidJavaRunnable(toClipBoardOnUiThread));
}
}
void toClipBoardOnUiThread(){
AndroidJavaClass Context = new AndroidJavaClass ("android.content.Context");
AndroidJavaObject CLIPBOARD_SERVICE = Context.GetStatic<AndroidJavaObject> ("CLIPBOARD_SERVICE");
AndroidJavaObject clipboardMgr = currentActivity.Call<AndroidJavaObject> ("getSystemService", CLIPBOARD_SERVICE);
AndroidJavaClass ClipData = new AndroidJavaClass ("android.content.ClipData");
AndroidJavaObject clipData = ClipData.CallStatic<AndroidJavaObject> ("newPlainText", "deltaBit", input);
clipboardMgr.Call ("setPrimaryClip", clipData);
showToastOnUiThread ("Copied to clipboard:" + input);
}
void showToastOnUiThread(string toastString){
this.toastString = toastString;
currentActivity.Call ("runOnUiThread", new AndroidJavaRunnable (showToast));
}
void showToast(){
AndroidJavaClass Toast = new AndroidJavaClass ("android.widget.Toast");
AndroidJavaObject javaString = new AndroidJavaObject ("java.lang.String", toastString);
AndroidJavaObject toast = Toast.CallStatic<AndroidJavaObject> ("makeText", context, javaString, Toast.GetStatic<int> ("LENGTH_SHORT"));
toast.Call ("show");
}
}
在使用过程中,只需要将脚本挂载在一个GameObject中,然后直接调用ToAndroidClipBoard方法即可弹出土司
随后我仔细的查看了代码,接下来我会进行分析代码,当然 AndroidJavaClass,GetStatic,Call这个我就不讲了,这个从外貌就能知道意思
首先
if (Application.platform == RuntimePlatform.Android) {
UnityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
currentActivity = UnityPlayer.GetStatic<AndroidJavaObject> ("currentActivity");
context = currentActivity.Call<AndroidJavaObject> ("getApplicationContext");
}
这块代码我就不说了,如果你导出过Android工程的话,就会对里面的东西有所了解,当然,没看过也没关系,我简单讲解一下,首先UnityPlayer就是你游戏主要的东西,在Android代码中,它会写成这样
UnityPlayer player=new UnityPler();
setContentView(player);
如果对android代码不清楚的同学,也可以百度一下,setContentView就是设置界面
currentActivity:这个东西我大概估计了一下,应该是获取当前显示的Activity.
不懂得人可能会问Activity是什么,这个我简单讲解一下,Activity是Android的一个最重要的东西,简单来说你见到的每一个界面都是运行在Activity上
Context :在Android中叫做上下文,Context你可以把他想象成一个大环境,只有在再这个环境下我们才能读取资源等等,在这里我不细说了,感兴趣的可以去看看android编程
public void ToAndroidClipBoard(string s){
if (Application.platform == RuntimePlatform.Android) {
input=s;
//runOnUiThread是让后面的方法运行在主线程,这一点也是Android的知识,在Android中像土司这样的东西必须要在主线程调用,
//否则会报异常,这一点希望各位能够记住
currentActivity.Call("runOnUiThread",new AndroidJavaRunnable(toClipBoardOnUiThread));
}
}
随后它会调用toClipBoardOnUiThread()方法,这个方法是将String字符串添加到剪贴板中,具体的我就不说了,毕竟我们主要是Toast,而这个的android的代码我也会贴出来
void toClipBoardOnUiThread(){
AndroidJavaClass Context = new AndroidJavaClass ("android.content.Context");
AndroidJavaObject CLIPBOARD_SERVICE = Context.GetStatic<AndroidJavaObject> ("CLIPBOARD_SERVICE");
//得到剪贴板管理器的对象
AndroidJavaObject clipboardMgr = currentActivity.Call<AndroidJavaObject> ("getSystemService", CLIPBOARD_SERVICE);
AndroidJavaClass ClipData = new AndroidJavaClass ("android.content.ClipData");
AndroidJavaObject clipData = ClipData.CallStatic<AndroidJavaObject> ("newPlainText", "deltaBit", input);
clipboardMgr.Call ("setPrimaryClip", clipData);
showToastOnUiThread ("Copied to clipboard:" + input);
}
Android:
public void toClipBoardOnUiThread(String input){
ClipboardManager systemService = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
ClipData data=ClipData.newPlainText("deltaBit",input);
systemService.setPrimaryClip(data);
}
最后就到我们的土司阶段了
void showToastOnUiThread(string toastString){
this.toastString = toastString;
currentActivity.Call ("runOnUiThread", new AndroidJavaRunnable (showToast));
}
void showToast(){
AndroidJavaClass Toast = new AndroidJavaClass ("android.widget.Toast");
AndroidJavaObject javaString = new AndroidJavaObject ("java.lang.String", toastString);
AndroidJavaObject toast = Toast.CallStatic<AndroidJavaObject> ("makeText", context, javaString, Toast.GetStatic<int> ("LENGTH_SHORT"));
toast.Call ("show");
}
首先还是runOnUiThread,调用showToast方法
随后通过AndroidJavaClass得到Toast类,通过AndroidJavaObject获取JavaString对象,随后通过CallStatic静态调用Toast中的静态方法makeText,将context,string,"LENGTH_SHORT"传进去,第三个参数是Toast类定义的int静态值,对应的是Toast显示的长度,当然你也可以直接传进0或者1,最后,用toast类调用show方法即可显示
Android代码就是我上面写的那句代码
所以下面我将那个类修改了一下,这个类就是单纯弹土司的类,需要的可以直接粘贴
using UnityEngine;
using System.Collections;
public class Toast : MonoBehaviour {
string data;//Toast要显示的数据
AndroidJavaObject currentActivity;
AndroidJavaClass UnityPlayer;
AndroidJavaObject context;
// Use this for initialization
void Start () {
if (Application.platform == RuntimePlatform.Android) {
UnityPlayer = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
currentActivity = UnityPlayer.GetStatic<AndroidJavaObject> ("currentActivity");
context = currentActivity.Call<AndroidJavaObject> ("getApplicationContext");
}
}
public void SetToast(string data){
if (Application.platform == RuntimePlatform.Android) {
this.data = data;
currentActivity.Call("runOnUiThread",new AndroidJavaRunnable(ShowToast));
}
}
void ShowToast(){
AndroidJavaClass Toast = new AndroidJavaClass ("android.widget.Toast");
AndroidJavaObject javaString = new AndroidJavaObject ("java.lang.String", data);
AndroidJavaObject toast = Toast.CallStatic<AndroidJavaObject> ("makeText", context, javaString, Toast.GetStatic<int> ("LENGTH_SHORT"));
toast.Call ("show");
}
}