Android Plugins For Unity:Android Studio
最近在對接Android平臺的SDK,由於工作保密原因,這裡做一個Demo進行研發記錄!
因為專案要求由Unity進行開發,所以需要將Android的東西做成外掛匯出給Unity呼叫,所以參考官方提供的文獻:https://docs.unity3d.com/Manual/PluginsForAndroid.html ;
進行了進一步修改!
外掛使用 Android Studio2.2 進行開發編寫:Android Studio 有個好處,就是可以將res中的資原始檔一起打包匯出成aar包!
開發流程:
一、首先建立一個空專案:
二、在空工程中新建一個Module(Android Library):
三、在本地的Unity安裝路徑中找到classes.jar包:(可以通過搜尋查詢)
D:\Unity\Editor\Data\PlaybackEngines\androidplayer\Variations\mono\Development\Classes\classes.jar
四、將Unity的classes.jar包拷貝到剛才新建的 Android Library 模組下的 libs 資料夾中 : AndroidLibrary/libs/classes.jar
五、在AndroidLibrary中的build.gradle檔案中新增幾句程式碼,將Unity的classes.jar新增到依賴中,這樣才可以正常使用Unity的Java類:
repositories{
flatDir{
dirs 'libs'
}
}
dependencies{
compile files(libs/classes.jar)
}
六、到這裡開始就可以進行正常的Plugins外掛編寫了:
package com.wjt.plugins.customactivity;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Window;
import android.widget.Toast;
import com.unity3d.player.UnityPlayer;
public class CustomProxyActivity extends Activity
{
private final String TAG = getPackageName();
//許可權申請碼
private static final int READ_PHONE_STATE_REQUEST_CODE = 1;
//Android 6.0 需要動態申請某些許可權 =====》下列許可權還必須在AndroidManifest.xml檔案中進行宣告
private static final String[] DANGEROUS_PERMISSION = { "android.permission.READ_PHONE_STATE", "android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE" };
protected UnityPlayer mUnityPlayer;
public void PermissionRequest()
{
Log.e(this.TAG, "申請許可權!");
runOnUiThread(new Runnable()
{
public void run() {
if (Build.VERSION.SDK_INT >= 23)
if ((ActivityCompat.checkSelfPermission(CustomProxyActivity.this, "android.permission.READ_PHONE_STATE") != 0) ||
(ActivityCompat.checkSelfPermission(CustomProxyActivity.this, "android.permission.READ_EXTERNAL_STORAGE") != 0) ||
(ActivityCompat.checkSelfPermission(CustomProxyActivity.this, "android.permission.WRITE_EXTERNAL_STORAGE") != 0))
{
//申請許可權
ActivityCompat.requestPermissions(CustomProxyActivity.this, CustomProxyActivity.DANGEROUS_PERMISSION, 1);
}
else {
//許可權已經授予
Log.i(CustomProxyActivity.this.TAG, "許可權已經授予");
Toast.makeText(CustomProxyActivity.this.getApplicationContext(), "許可權已經授予!", 0).show();
}
}
});
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
if (requestCode == 1) {
if (grantResults[0] == 0)
{
//許可權授予成功
Toast.makeText(getApplicationContext(), "成功獲得授權!", 0).show();
Log.i(this.TAG, "成功獲得授權");
} else {
Log.i(this.TAG, "未獲得授權");
Toast.makeText(getApplicationContext(), "許可權拒絕,準備退出,請處理後事!", 0).show();
}
}
else super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
Log.i(this.TAG, String.format("請求碼 :%d , 結果碼 :%d , Intent :%s", new Object[] { Integer.valueOf(requestCode), Integer.valueOf(resultCode), data.getDataString() }));
Toast.makeText(this, String.format("請求碼 :%d , 結果碼 :%d , Intent :%s", new Object[] { Integer.valueOf(requestCode), Integer.valueOf(resultCode), data.getDataString() }), 0).show();
}
protected void onCreate(Bundle savedInstanceState)
{
requestWindowFeature(1);
super.onCreate(savedInstanceState);
getWindow().takeSurface(null);
getWindow().setFormat(2);
this.mUnityPlayer = new UnityPlayer(this);
setContentView(this.mUnityPlayer);
this.mUnityPlayer.requestFocus();
}
protected void onDestroy()
{
this.mUnityPlayer.quit();
super.onDestroy();
}
protected void onPause()
{
super.onPause();
this.mUnityPlayer.pause();
}
protected void onResume()
{
super.onResume();
this.mUnityPlayer.resume();
}
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
this.mUnityPlayer.configurationChanged(newConfig);
}
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
this.mUnityPlayer.windowFocusChanged(hasFocus);
}
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == 2)
return this.mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
return this.mUnityPlayer.injectEvent(event);
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return this.mUnityPlayer.injectEvent(event);
}
public boolean onTouchEvent(MotionEvent event)
{
return this.mUnityPlayer.injectEvent(event);
}
public boolean onGenericMotionEvent(MotionEvent event)
{
return this.mUnityPlayer.injectEvent(event);
}
}
//建立res資源
package com.wjt.plugins.customactivity;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
import com.wjt.plugins.R.id;
import com.wjt.plugins.R.layout;
public class onStartActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_onstartactivity);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener()
{
public void onClick(View view) {
Toast.makeText(onStartActivity.this, "onStartActivity is ready start!", 0).show();
}
});
}
}
編寫好AndroidPlugins後 Rebuilt Project ,完成後就可以在當前AndroidLibrary模組下的 build檔案中找到匯出的aar包了:AndroidLibrary\build\outputs\aar\***.aar
七、使用:將匯出的*.aar包拷貝到Unity專案中的Assets\Plugins\Android\ 目錄下,然後用zip壓縮工具開啟aar包,將libs\資料夾下的classes.jar包檔案刪除掉,否則在打包Unity專案的時候會報錯!
八、為Unity專案配置AndroidManifest.xml檔案:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wjt.plugins"
android:installLocation="preferExternal" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:versionCode="1" android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" android:targetSdkVersion="24" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.GET_TASKS"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_LOGS"/>
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true"/>
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true">
<activity android:name="com.wjt.plugins.customactivity.CustomProxyActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> </intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false" />
</activity> <activity android:name="com.wjt.plugins.customactivity.onStartActivity" android:screenOrientation="landscape"/>
</application> </manifest>九、在Unity中進行呼叫:
隨意建立一個C#Script指令碼,在Start()方法中新增幾行程式碼進行調動:
AndroidJavaClass jc = new UnityEngine.AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject activity = jc.GetStatic<UnityEngine.AndroidJavaObject>("currentActivity");
activity.Call("PermissionRequest");
就這樣,即可呼叫外掛裡的方法了,並且會有具體的響應。
到此,整個記錄完成。。。