【Unity】調(diào)用安卓相機及相冊

寫在前面

這個sdk在前一段時間就完成了音比,今天又拿來修改了一下妖滔,徹底把權(quán)限問題多解決了隧哮。經(jīng)過這次寫這個sdk,深深的發(fā)現(xiàn)安卓在一次又一次升級用戶體驗座舍,但是沮翔,但是很是折磨程序員啊。一開始我以為這是一個很簡單的事曲秉,結(jié)果被各種權(quán)限版本設(shè)置搞得都要奔潰了采蚀。

開始

其實網(wǎng)上的文章都很詳細比如文章1http://www.voidcn.com/article/p-ehdfbrsl-nh.html文章2http://www.voidcn.com/article/p-ehdfbrsl-nh.html )。 其實實現(xiàn)過程都大同小異承二,我們主要來看我遇到得的問題榆鼠,當然這些問題都是在6.0以上的版本出現(xiàn)的問題,之前的都沒有亥鸠。

安卓6.0以上獲取攝像機權(quán)限

在最開始我們在AndroidManifest.xml文件中添加獲取相機權(quán)限妆够,如下

<uses-permission android:name="android.permission.CAMERA"/>

然后運行程序第一次并沒有提示我獲得相機權(quán)限,然后再點擊打開相機閃退负蚊,媽耶神妹。然后就查資料說,相機這類權(quán)限屬于危險級家妆,需要動態(tài)請求鸵荠。所以這里就開始編寫動態(tài)請求,網(wǎng)上蠻多文章說這個的伤极,大多都需要使用其他什么插件得的腰鬼。官方給出的代碼:

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}

更多詳細的可以看看官網(wǎng)文檔https://developer.android.com/training/permissions/requesting)。 這里用的ActivityCompat是使用的Android.support.v4的架包塑荒。所以導(dǎo)入unity后我們還需要導(dǎo)入這個架包不然的話會報錯熄赡。看有文章說這個架包在安卓SDK的目錄下可以找到齿税,目錄: AndroidSDK/extras/android/m2repository/com/android/support/support-v4

里面有很多版本的彼硫,移到unity中,沒有用凌箕,還是報錯E±骸!牵舱!可能是我用的版本不對串绩。這里我使用的是之前接GooglePlay的SDK里面的架包。加進去了沒有報錯了芜壁。但是·······

點擊打開相機出來了礁凡,選擇權(quán)限框高氮,但是是閃現(xiàn)的。對就是閃現(xiàn)的顷牌。

權(quán)限閃現(xiàn)

沒辦法剪芍,查了很久,然后看unity官方文檔https://docs.unity3d.com/Manual/android-manifest.html ) 中說的是需要再加一個設(shè)置到AndroidManifest里窟蓝,加在Application之間或者Activity即可罪裹。

<meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" />

因為unity本身是不支持動態(tài)權(quán)限系統(tǒng)。同時我又看到一個玄學答案运挫,在你的代碼里加入這個:

/// <summary>
/// 無用方法状共,用來打開攝像頭權(quán)限
/// </summary>
/// <returns></returns>
private IEnumerator OpenCameraPermisson()
{
    yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
    if (!Application.HasUserAuthorization(UserAuthorization.WebCam)) yield break;
    WebCamDevice[] devices = WebCamTexture.devices;
}

這兩個是我一起加的好像都有效果,調(diào)用webcam時unity會自動提示你打開相機權(quán)限谁帕。就這樣解決了問題口芍。

在動態(tài)獲取權(quán)限那個地方修改了一下寫法,不太想使用其他的架包啥的雇卷,我的寫法是:

//先檢測權(quán)限
public void OpenTakePhoto() {
    if (Build.VERSION.SDK_INT > 22) {
        if (this.checkSelfPermission(android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {

            //先判斷有沒有權(quán)限 鬓椭,沒有就在這里進行權(quán)限的申請
            this.requestPermissions(
                    new String[]{android.Manifest.permission.CAMERA}, CAMERA_OK);
        } else {
            TakePhoto();
        }
    } else {
        TakePhoto();
    }

}

簡單點的說就是把ActivityCompat替換成當前的Activity就可以。這樣就可以不使用support.v4架包关划。

相機打開閃退

對的小染,你沒看錯。不過這個很快就解決了贮折。這個問題出現(xiàn)的原因主要是由于在Android 7.0以后裤翩,用了Content Uri 替換了原本的File Uri,故在targetSdkVersion=24的時候调榄,部分 “Uri.fromFile()“方法就不適用了踊赠。 File Uri 與 Content Uri 的區(qū)別 - File Uri 對應(yīng)的是文件本身的存儲路徑 - Content Uri 對應(yīng)的是文件在Content Provider的路徑 所以在android 7.0 以上,我們就需要將File Uri轉(zhuǎn)換為 Content Uri每庆。這里寫一個轉(zhuǎn)化的方法:

/**
 * 轉(zhuǎn)換 content:// uri
 * 7.0以后使用
 *
 * @param imageFile
 * @return
 */
public Uri getImageContentUri(File imageFile) {
    String filePath = imageFile.getAbsolutePath();
    Cursor cursor = getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            new String[]{MediaStore.Images.Media._ID},
            MediaStore.Images.Media.DATA + "=? ",
            new String[]{filePath}, null);

    if (cursor != null && cursor.moveToFirst()) {
        int id = cursor.getInt(cursor
                .getColumnIndex(MediaStore.MediaColumns._ID));
        Uri baseUri = Uri.parse("content://media/external/images/media");
        return Uri.withAppendedPath(baseUri, "" + id);
    } else {
        if (imageFile.exists()) {
            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.DATA, filePath);
            return getContentResolver().insert(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        } else {
            return null;
        }
    }

}

然后再打開相機的地方做一個選擇:

//打開相機
private void TakePhoto() {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        File outFile = new File(UnityUsePicturePath);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, getImageContentUri(outFile));
    } else {
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(UnityUsePicturePath)));
    }

    startActivityForResult(intent, PHOTOHRAPH);
}

存儲權(quán)限問題

這里我們需要添加存儲的權(quán)限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

我們可以在打開相冊的時候檢測一下筐带,動態(tài)請求一下。

代碼

我把java代碼寫成了Activity類缤灵,然后我們直接在unity中的調(diào)用傳入?yún)?shù)即可:

    //獲得照片
    public void GetPhoto(GetPhotoType photoType, bool isCutPicture = false)
    {
        var strType = Enum.GetName(typeof(GetPhotoType), photoType);
        AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent", unityActivity, gallerySdk);

        intentObject.Call<AndroidJavaObject>("putExtra", "type", strType);
        intentObject.Call<AndroidJavaObject>("putExtra", "UnityPersistentDataPath", Application.persistentDataPath);
        intentObject.Call<AndroidJavaObject>("putExtra", "isCutPicture", isCutPicture);
        unityActivity.Call("startActivity", intentObject);
        Debug.Log("GetPhoto Android startActivity");
    }

這樣我們就可以不需要重新寫AndroidManifest了伦籍,只需要在其中申明一下Activity即可:

<!-- 打開相冊及相機 設(shè)置為透明 -->
        <!--  android:screenOrientation="portrait" android:configChanges="orientation|screenSize|keyboardHidden|keyboard|"解決相機Activity無法關(guān)閉問題 -->
        <activity android:name="com.unity.gallerylibrary.GalleryManager"  android:screenOrientation="portrait" android:configChanges="orientation|screenSize|keyboardHidden|keyboard|">
           <!-- 解決這個問題 Only fullscreen opaque activities can request orientation -->
            <item name="android:windowIsTranslucent">false</item>
            <item name="android:windowDisablePreview">true</item>
        </activity>

其他的看一下源碼就可以了。很簡單腮出。

java代碼

unity 代碼

AndroidManifest

示例代碼

void OnGUI()
{
    if (GUILayout.Button("Take Photo", GUILayout.Width(200), GUILayout.Height(200)))
    {
        GalleryManager.Instance.GetPhoto(GetPhotoType.Carmera, (texture) => { rawImage.texture = texture; });
    }
    if (GUILayout.Button("Open Gallery", GUILayout.Width(200), GUILayout.Height(200)))
    {
        GalleryManager.Instance.GetPhoto(GetPhotoType.Gallery, (texture) => { rawImage.texture = texture; });
    }
    if (GUILayout.Button("Show Image", GUILayout.Width(200), GUILayout.Height(200)))
    {

        StartCoroutine(GetImageByPath(Application.persistentDataPath + "/UNITY_GALLERY_PICTUER.png"));
    }
}

效果圖

參考文章:

http://www.voidcn.com/article/p-ehdfbrsl-nh.html
https://www.xuanyusong.com/archives/1480
https://blog.csdn.net/dengmengxin/article/details/38702467
權(quán)限:
http://www.reibang.com/p/765603bebced
https://blog.csdn.net/beijinghsj/article/details/53581764
https://docs.unity3d.com/Manual/android-manifest.html
https://blog.csdn.net/haojiagou/article/details/80761709

3.jpg

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末帖鸦,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子胚嘲,更是在濱河造成了極大的恐慌作儿,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馋劈,死亡現(xiàn)場離奇詭異攻锰,居然都是意外死亡晾嘶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門口注,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人君珠,你說我怎么就攤上這事寝志。” “怎么了策添?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵材部,是天一觀的道長。 經(jīng)常有香客問我唯竹,道長乐导,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任浸颓,我火速辦了婚禮物臂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘产上。我一直安慰自己棵磷,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布晋涣。 她就那樣靜靜地躺著仪媒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谢鹊。 梳的紋絲不亂的頭發(fā)上算吩,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音佃扼,去河邊找鬼偎巢。 笑死,一個胖子當著我的面吹牛兼耀,可吹牛的內(nèi)容都是我干的艘狭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼翠订,長吁一口氣:“原來是場噩夢啊……” “哼巢音!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起尽超,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤官撼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后似谁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傲绣,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡掠哥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了秃诵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片续搀。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖菠净,靈堂內(nèi)的尸體忽然破棺而出禁舷,到底是詐尸還是另有隱情,我是刑警寧澤毅往,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布牵咙,位于F島的核電站,受9級特大地震影響攀唯,放射性物質(zhì)發(fā)生泄漏洁桌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一侯嘀、第九天 我趴在偏房一處隱蔽的房頂上張望另凌。 院中可真熱鬧,春花似錦戒幔、人聲如沸途茫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囊卜。三九已至,卻和暖如春错沃,著一層夾襖步出監(jiān)牢的瞬間栅组,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工枢析, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留玉掸,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓醒叁,卻偏偏與公主長得像司浪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子把沼,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

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