Unity和Android通信以及AndroidManifest的合并

前言:

????Unity和android交互,這個(gè)問(wèn)題,在百度搜一下,解決方案還是蠻多的,起初我也是照著百度出來(lái)的帖子一步步實(shí)現(xiàn)了.但是!大部分帖子只管功能實(shí)現(xiàn)根本不講緣由,且實(shí)現(xiàn)的功能比較死板.看完這樣的帖子,對(duì)學(xué)習(xí)完全沒(méi)有幫助啊喂!想要在項(xiàng)目中使用交互代碼相應(yīng)的也會(huì)遇到許多問(wèn)題(后面會(huì)說(shuō)遇到的問(wèn)題,以及解決方案).

適用人群:

1.unity開(kāi)發(fā)者,不會(huì)使用AndroidStudio,通過(guò)本教程,可以了解Android Studio的基本使用.

2.搜索了很多unity,Android交互文章卻沒(méi)找到合適解決方案的同學(xué).


使用jar還是aar進(jìn)行通信?

Jar中包含了原生java代碼,如果我們只是測(cè)試通信,一個(gè)簡(jiǎn)單的jar包就能夠通信,然而實(shí)際開(kāi)發(fā)中,一般不可能只用一個(gè)jar包,在android工程中一般都會(huì)引用很多jar包,

aar大概是設(shè)計(jì)出來(lái)用來(lái)替代jar來(lái)進(jìn)行通信的,不僅包含了jar 還包含了提供的android資源(圖片,布局文件等).這也是aar包比jar大的原因,我們可以通過(guò)刪除不相關(guān)內(nèi)容來(lái)降低aar包的大小.

AndroidStudio:

打開(kāi)AndroidStudio-? ? NewProject:


新建activity之后,要在activity中引用unity的方法就需要引入unity的jar包,根據(jù)以下目錄找到unity提供的jar:

根據(jù)在unity中選擇的打包方式,復(fù)制出來(lái)文件夾中的jar包

放在android studio中的libs文件夾中

這個(gè)classes.Jar是unity給安卓寫(xiě)的腳本,在android中引用了這個(gè)jar包,就可以調(diào)用里面的方法(各位原生老哥應(yīng)該比我清楚....),右鍵classes.jar 最下面有個(gè)add as a Library 或者

導(dǎo)入成功后,就可以引入unity提供的package了

根據(jù)我想實(shí)現(xiàn)的需求,需要引用兩個(gè)package:

1. 在安卓原生中調(diào)用unity方法(向unity傳遞數(shù)據(jù)),import com.unity3d.player.UnityPlayer

2. 為了unity中能找到并調(diào)用andorid方法( import com.unity3d.player.UnityplayerAcitvity,來(lái)繼承UnityPlayerActivity)

對(duì)默認(rèn)的activity進(jìn)行以下更改:

Android Studio端 邏輯代碼編寫(xiě)完畢.這里講解下unity android相互調(diào)用API的使用規(guī)則:

Android調(diào)unity:

?unitySendMessage需要三個(gè)參數(shù):s1(string):unity 場(chǎng)景中的的gameobject的name .s2(string):該gameobject上的腳本上的方法名 s3(string):傳遞的消息內(nèi)容,可以是json,xml之類(lèi)的.也就是說(shuō)unity通過(guò)尋找場(chǎng)景中的gameobject,調(diào)用unity自己的sendmessage來(lái)傳遞消息(這里使用的是Unity提供的unitysendMessage往unity回調(diào)數(shù)據(jù),它是通過(guò)反射實(shí)現(xiàn)的,這個(gè)帖子http://www.reibang.com/p/f5b20d43315a提供了java中反射的實(shí)現(xiàn),可以不用unity的方法直接實(shí)現(xiàn)通信).

Unity調(diào)用android:

Unity官網(wǎng)提供的死代碼以及網(wǎng)上一半帖子的代碼如上,大概意思是通過(guò)包名找到了java類(lèi), 但是是具體哪一個(gè)類(lèi)的對(duì)象需要用”currentActivity”獲取到.這里我推測(cè)我們?cè)赼ndroid 中新建的MainActivity是繼承了UnityPlayerActivity才能被以上兩行代碼找到(這個(gè)必須要繼承UnityPlayerActivity 才能被找到 很雞肋很雞肋).

接下來(lái)導(dǎo)出aar包:

Android Studio默認(rèn)build會(huì)生成apk,此時(shí)需要更改build.gradle來(lái)讓Android studio導(dǎo)出aar包

設(shè)置完畢后,點(diǎn)擊build-RebuildProject進(jìn)度走完后,打開(kāi)build/outputs/aar找到導(dǎo)出的aar

右鍵,show In Explorer在文件夾中顯示它

可以看到它是可以被解壓軟件打開(kāi)的,我們可以打開(kāi)看下,來(lái)刪除那些我們不需要的內(nèi)容

由于在Android Studio我無(wú)腦build導(dǎo)致build出來(lái)一大堆用不到的東西,我又不知道如何在Android studio中不導(dǎo)出這些,所以現(xiàn)在直接操作aar刪除,首先要分辨出來(lái)哪些是有用的,哪些是無(wú)用的.

有用的:我寫(xiě)的兩個(gè)java類(lèi),猜測(cè)被自動(dòng)打入到aar包中外層的Classes.jar中了

無(wú)用的:事先從unity導(dǎo)入的jar包(存放在libs/classes.jar,至于它為啥和aar中的classes.jar名字一樣,我也不知道),布局文件,dpi文件 刪除完畢后,如下

Unity中:

在unity的 Assets目錄下新建Plugins/Android(Plugins文件夾必須是在Assets根目錄) 文件夾 拖入剛才的aar和AndroidManifest(此處應(yīng)該有疑問(wèn),為什么aar包中有AndroidManifest文件,還要在unity的目錄下還放置一個(gè)AndroidManifest)

在unity中新建name為AndroidCall的gameobject以及新建腳本,新建方法TestCall.


unity playersettings中packageName和Android activity的package要保持一致

大部分帖子寫(xiě)到這里展示一下調(diào)用成功的截圖,就結(jié)束了帖子...前面講到的很雞肋的unity獲取Android 對(duì)象的方式,就這樣雞肋下去了,準(zhǔn)確的來(lái)說(shuō),目前實(shí)現(xiàn)的unity和Android交互只是一個(gè)最基礎(chǔ)的demo,在實(shí)際項(xiàng)目開(kāi)發(fā)過(guò)程中根本不可能使用這種單一的方式.我相信這些朋友后面也都發(fā)現(xiàn)了它的缺點(diǎn),一部分網(wǎng)友更新了unity Android交互第二篇...,我認(rèn)為要想得心應(yīng)手的使用unity和底層通信就要了解其通信原理,但是在介紹通信原理之前必須要介紹一下AndroidManifest這個(gè)東西,它對(duì)我們理解如何通信至關(guān)重要.

AndroidManifest是什么?他有什么作用?

清單文件(Mainfest)普遍存在于各個(gè)平臺(tái)生成的項(xiàng)目中,是對(duì)指定內(nèi)容的一種描述,提供了指定內(nèi)容構(gòu)成有關(guān)的所有信息,且有唯一標(biāo)識(shí)作用,就像是一條http請(qǐng)求,header包含了對(duì)body體內(nèi)容的描述.

一般由以下幾部分構(gòu)成:

1.指定內(nèi)容的版本信息.

2.指定內(nèi)容對(duì)其他內(nèi)容的依賴(lài)

3.指定內(nèi)容的安全權(quán)限

AndroidManifest是Android中打包時(shí)生成的一個(gè)清單文件,位于根目錄:

1.包含了app要在Android系統(tǒng)上運(yùn)行的基礎(chǔ)信息:app圖標(biāo)(Icon),名稱(chēng)(product Name),橫屏還是豎屏(orientation),版本號(hào)(version)等等,在unity中是通過(guò)PlayerSettings的可視化界面配置app的基本信息的.這些內(nèi)容會(huì)在打包的時(shí)候?qū)懭階ndroidManifest中,有了這些基礎(chǔ)設(shè)置,該app安裝在Android設(shè)備上才會(huì)在桌面中顯示出來(lái).

2.設(shè)置程序入口.有了上一條說(shuō)的基礎(chǔ)配置之后,雖然能夠在Android中顯示,但是沒(méi)有設(shè)置要啟動(dòng)的Activity,會(huì)直接閃退.(平時(shí)正常打包出來(lái)的app能運(yùn)行是因?yàn)橐呀?jīng)設(shè)置好了程序入口Activity),在Android中應(yīng)該是允許配置多個(gè)activity,設(shè)置一個(gè)mainActivity,然后在activity中切換.unity打的Android只使用一個(gè)activity.

3.配置該app需要的Android功能:比如app需要開(kāi)啟攝像機(jī)或者麥克風(fēng),需要在Manifest中配置權(quán)限,否則Android不會(huì)彈出權(quán)限請(qǐng)求,權(quán)限部分需要<uses-permission>標(biāo)簽,再比如需要Android廣播接收器功能就需要配置<receiver>標(biāo)簽.

????Android開(kāi)發(fā)的同學(xué)都知道,每當(dāng)新建一個(gè)Activity ,就會(huì)生成一個(gè)Manifest文件,它用來(lái)指定當(dāng)前activity需要的各種配置.然后一個(gè)activity就可以通過(guò)設(shè)置gradle 來(lái)生成一個(gè)apk,運(yùn)行在Android設(shè)備上,那unity是如何生成apk的呢?我們新建一個(gè)unity工程并導(dǎo)出成Android Project來(lái)研究一下:

新建一個(gè)空的unity工程,將unity 的buildSettings上的export project勾選就可以將項(xiàng)目導(dǎo)出成Android project

使用AndroidStudio打開(kāi)該工程發(fā)現(xiàn),unity的export過(guò)程就是將unity的內(nèi)容導(dǎo)出成了一個(gè)activity,叫做UnityPlayerActivity,這個(gè)activity的packageName就是在unity的Android PlayerSettings中設(shè)置的packageName

前面說(shuō)到每個(gè)activity都包含Manifest文件,打開(kāi)Manifest文件如下


Unity打包出來(lái)的Manifest文件是根據(jù)存放在unity安裝目錄下的Manifest模板生成一個(gè)com.XXX(unity中設(shè)置的package).UnityPlayerActivity,所以我們unity的apk在Android設(shè)備中是通過(guò)Manifest中設(shè)置的啟動(dòng)項(xiàng)Activity啟動(dòng)的.

????????下面回過(guò)頭來(lái)看剛才那個(gè)測(cè)試demo的Manifest文件:

主要功能就是設(shè)置了com.axin.mylibrary.customActivity這個(gè)activity為啟動(dòng)activity,已知unity會(huì)自動(dòng)生成UnityPlayerActivity這個(gè)activity作為啟動(dòng)項(xiàng),如何把咱們的activity替換到Unity生成的Manifest文件中呢?官方文檔對(duì)此進(jìn)行了說(shuō)明:https://docs.unity3d.com/2017.4/Documentation/Manual/android-manifest.html?tdsourcetag=s_pctim_aiomsg

在unity中AndroidManifest文件的合并重點(diǎn)是這一句(已使用谷歌翻譯)

在unity中提供的AndroidManifest文件只能有一個(gè),它的目錄是Assets/Plugins/Android/AndroidManifest.xml,這也是我們前面在unity目錄下導(dǎo)入AndroidManifest的原因,下面展示下unity替我們合并的Manifest文件

? ??對(duì)比之前打包的空工程的AndroidManifest文件,啟動(dòng)項(xiàng)activity已經(jīng)變成了.customActivity,這就是我們?cè)赼ssets/plugins/Android目錄下放置的AndroidManifest文件中的內(nèi)容覆蓋了unity的fest文件模板生成的效果.

????由于unity的playersettings中設(shè)置的packageName和 aar包中Android activity的packge一致(此處應(yīng)該有疑問(wèn),我unity中的packageName應(yīng)該指定的是我司的公司名稱(chēng)和項(xiàng)目名稱(chēng),怎么能和第三方aar保持一致呢?也不能我用了阿里巴巴的aar,我就要讓我unity項(xiàng)目的packageName帶上阿里巴巴吧?),所以啟動(dòng)項(xiàng)activity就是com.axin.mylibrary.customactivty,另外customactivty又是繼承UnityPlayerActivity的

所以我們的代碼

獲取的就是這個(gè)java類(lèi)的對(duì)象(為了能用上述兩行代碼找到我們定義的activity,實(shí)際上是我們的activity搶占了unity默認(rèn)的啟動(dòng)activity,這會(huì)帶來(lái)不同程度的后果,但是如果我們沒(méi)有使用UnityPlayerActivity這個(gè)父類(lèi)的需求的話,我們盡量不要繼承它實(shí)現(xiàn)通信,下文會(huì)提到另一種調(diào)用javaclass對(duì)象的方法.)


????????此時(shí)調(diào)用AndroidCallUnity方法就會(huì)調(diào)用unity中的方法了.

? ??????以上簡(jiǎn)單的解釋了下我們的通信demo是如何運(yùn)行的,但是它僅僅是demo,下面我們分析一下實(shí)際項(xiàng)目的需求:

A.在unity中接入一個(gè)或者多個(gè)第三方sdk,意味著導(dǎo)入多個(gè)aar.

B.在Android原生中接入多個(gè)原生sdk,然后將數(shù)據(jù)傳回unity.

C.Unity項(xiàng)目最終只作為一個(gè)activity來(lái)運(yùn)行,如果各個(gè)aar都要搶占Activity入口,都要求unity項(xiàng)目packageName和自己保持一致那該怎么辦?(上文的測(cè)試demo搶占了Activity入口且要求項(xiàng)目packageName和aar的保持一致.網(wǎng)上搜索的unity Android通信帖子大部分都這樣寫(xiě)的)

????????情況A多為unity開(kāi)發(fā)者遇到,意味著unity中需要導(dǎo)入多個(gè)aar,就可能(我覺(jué)得導(dǎo)出的aar都會(huì)有Manifest文件,因?yàn)槲乙膊皇茿ndroid開(kāi)發(fā),不敢說(shuō)太絕對(duì))會(huì)附帶多個(gè)Manifest.多個(gè)AndroidManifest可能存在于unity項(xiàng)目工程中,也可能存在于aar包中.

對(duì)于Unity工程里的AndroidManifest:

眾多AndroidManifest可能擁有不同的系統(tǒng)權(quán)限或不同的APILevel等.這時(shí)候就應(yīng)該合并不同的Manifest.前面說(shuō)到unity的項(xiàng)目中只能存在一個(gè)AndroidManifest(起初我以為AndroidManifest只要放在Android目錄下就可以,unity中的editor文件夾,lib文件夾貌似都是這個(gè)邏輯,覺(jué)得多個(gè)Manifest文件unity會(huì)幫我們合并,事實(shí)上只要assets/Plugins/Android下的fest文件才能被合并,害我在這里卡住了很久),所以就需要手動(dòng)合并這些Manifest,只保留一份在Plugins/Android目錄下.保證手動(dòng)合并的Manifest中只有一個(gè)MainActivity.且這個(gè)activity盡量不主動(dòng)設(shè)置,讓unity去生成默認(rèn)的就可以.合并方法是復(fù)制粘貼....,即把非指定路徑下的Manifest文件中和指定路徑下Manifest文件不同的東西復(fù)制過(guò)去...比如權(quán)限什么的,最終文本還是要符合x(chóng)ml結(jié)構(gòu)的.

對(duì)于存在于aar包中的Manifest文件:?

????????打包過(guò)程中會(huì)根據(jù)谷歌的固定算法進(jìn)行合并,unity打包apk的流程大概是先打成Android 工程,再利用Android中的Gradle的Task打出apk,谷歌的合并算法應(yīng)該是在Task里,和unity沒(méi)什么關(guān)系,情況B和這個(gè)情況類(lèi)似,AndroidStudio也是依賴(lài)Gradle打包的.關(guān)于AndroidStudio中Manifest的合并原理:http://www.reibang.com/p/0febcb3625d9

AndroidManifest總結(jié):

????????根據(jù)分析unity中export的Android project分析發(fā)現(xiàn),unity是根據(jù)Unity的存放目錄下的AndroidManifest模板和Assets/Plugins/Android/AndroidManifest.XML 合并生成一個(gè)AndroidManifest,作為unityPlayerActivity的配置文件.unity項(xiàng)目目錄下的fset文件和aar包中的fest文件不同之處在于,unity中的fest通常搶占了入口Activity或?qū)nity默認(rèn)Activity進(jìn)行了一些修改,而aar包中的fest文件通常只包含該aar需要的系統(tǒng)權(quán)限和API Level ,該部分會(huì)在Gradle的task中被谷歌算法合并.

情況C的解決方案:

1.如果接入的第三方sdk都是原生Android Sdk,則可以在Android Studio中新建一個(gè)和Unity工程packageName一樣的Activity,整合眾多sdk要使用的API在一個(gè)Activity里,然后這個(gè)Activity設(shè)置為Main入口,放置新的AndroidManifest文件在unity指定文件夾下,下面這個(gè)教程貼是這么做的:https://blog.csdn.net/LIQIANGEASTSUN/article/details/78805902

2.不使用activity,直接使用Java類(lèi),Unity中可以通過(guò)new AndroidJavaObject(“包名”)直接生成一個(gè)java對(duì)象,來(lái)調(diào)用其中的方法(直接繼承UnityPlayerActivity主要是方便查找到activity ),各個(gè)sdk自己各自維護(hù)一個(gè)java類(lèi),提供unity調(diào)用的方法,在unity中通過(guò)unity的方式直接new這個(gè)java類(lèi)來(lái)調(diào)用(需要提供包名+類(lèi)名),在unity中整合各個(gè)第三方sdk,此方案不需要在AndroidStudio中新建activity,因?yàn)椴恍枰獡屨糰ctivity所以也不需要在unity文件夾下放置AndroidManifest,打包過(guò)程中會(huì)自動(dòng)合并aar包中的fest.

步驟如下:

首先,在AndroidStudio中新建一個(gè)java類(lèi):customSendMessage

導(dǎo)入unity中包含sendmessage的package(如何導(dǎo)入在上文) ,寫(xiě)一個(gè)AndroidCallUnity 方法

將aar導(dǎo)出后直接放到plugins/Android目錄下,(導(dǎo)出步驟在上文),在unity中

在java中有可能要用到上下文,這里的上下文(什么是上下文可以百度搜一下,大概指的就是當(dāng)前運(yùn)行的程序域吧)指的是當(dāng)前的Activity,獲取當(dāng)前activity 返回給java


文章完畢,如有錯(cuò)誤,還請(qǐng)各位大佬糾正,我會(huì)第一時(shí)間進(jìn)行修改,謝謝大家.

我的CSDN地址:

https://blog.csdn.net/weixin_39106746/article/details/103469620

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灶似,一起剝皮案震驚了整個(gè)濱河市坏快,隨后出現(xiàn)的幾起案子步脓,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡遮怜,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)鸿市,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锯梁,“玉大人,你說(shuō)我怎么就攤上這事焰情∧暗剩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵内舟,是天一觀的道長(zhǎng)冯遂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)谒获,這世上最難降的妖魔是什么蛤肌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮批狱,結(jié)果婚禮上裸准,老公的妹妹穿的比我還像新娘。我一直安慰自己赔硫,他們只是感情好炒俱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般权悟。 火紅的嫁衣襯著肌膚如雪砸王。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,443評(píng)論 1 302
  • 那天峦阁,我揣著相機(jī)與錄音谦铃,去河邊找鬼。 笑死榔昔,一個(gè)胖子當(dāng)著我的面吹牛驹闰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撒会,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嘹朗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了诵肛?” 一聲冷哼從身側(cè)響起屹培,我...
    開(kāi)封第一講書(shū)人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怔檩,沒(méi)想到半個(gè)月后惫谤,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡珠洗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了若专。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片许蓖。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖调衰,靈堂內(nèi)的尸體忽然破棺而出膊爪,到底是詐尸還是另有隱情,我是刑警寧澤嚎莉,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布米酬,位于F島的核電站,受9級(jí)特大地震影響趋箩,放射性物質(zhì)發(fā)生泄漏赃额。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一叫确、第九天 我趴在偏房一處隱蔽的房頂上張望跳芳。 院中可真熱鬧,春花似錦竹勉、人聲如沸飞盆。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吓歇。三九已至孽水,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間城看,已是汗流浹背女气。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留析命,地道東北人主卫。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鹃愤,于是被迫代替她去往敵國(guó)和親簇搅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容