1. 程式人生 > >Android Plugins For Unity:Android Studio

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");
就這樣,即可呼叫外掛裡的方法了,並且會有具體的響應。
到此,整個記錄完成。。。