Android 6.0以降のアクセス許可に問題があります。
私が取り組んでいるゲームはWRITE_EXTERNAL_STORAGE権限を使用していました。 Android 6.0以降では、ユーザーに許可を求める警告を表示する必要がありました。
このアラートを削除するリクエストを受け取りました。つまり、ゲームはWRITE_EXTERNAL_STORAGEを使用できなくなります。
技術的には、ゲームは現在、外部ストレージの書き込みと読み取りを行っていません。すべての保存およびキャッシュされたファイルは、アプリケーション固有のディレクトリ(/storage/emulated/0/Android/data/com.company.productname)に保存されますが、ゲームは保存されているOBBファイルを読み取る(場合によってはダウンロードする)必要があります/storage/emulated/0/Android/obb/com.company.productnameディレクトリ。
デバイスにWRITE_EXTERNAL_STORAGEまたはREAD_EXTERNAL_STORAGEがなくても、ゲームはこのディレクトリにアクセスできます。
しかし、次のディレクトリにはアクセスできません:
ストアからのゲームのダウンロードをシミュレートするために、アルファテストを使用してそれを確認しました。
ストレージへのアクセス許可が(アプリの設定を介して)与えられると、すべてが正常に実行されます。
OBBはどのようにマウントされますか?
私が使用しているUnreal Engine 4は、OBBファイルを処理するためにCのopen()関数を使用しています。
int32 Handle = open(LocalPath, O_RDONLY);
ここで、LocalPathはobbファイルへのフルパスです:/storage/emulated/0/Android/obb/com.company.productname/main.10003.com.company.productname.obb
質問は:
問題は別の場所に記載されているようですが、正確な問題であることを知らなかったため、見つけることができませんでした...
https://code.google.com/p/Android/issues/detail?id=197287
API23は、何らかの理由でOBBのユーザーをrootに設定したものであり、適切なユーザーではありません。そのため、アプリはそれにアクセスできません。
デバイスを再起動した後、すべてが正常に動作します。
現時点では、これに対する明確な回避策はありません。
すべての必要かつ役立つ情報を提供してくれて@Larryに感謝します:)
ストアからのアプリケーションに書き込み権限があるかどうかを確認してください。
適切なソリューションを指摘してくれた@Larryに感謝します。
なぜAOSP APK拡張サポートlibrayが許可なしに機能しないのか疑問に思う方のために、変更されたAPKExpansionSupport.Java
package com.Android.vending.expansion.zipfile;
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.Apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Java.io.File;
import Java.io.IOException;
import Java.util.Vector;
import Android.content.Context;
public class APKExpansionSupport {
public static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) {
String packageName = ctx.getPackageName();
Vector<String> ret = new Vector<>(2);
File expPath = ctx.getObbDir();
// Check that expansion file path exists
if (expPath.exists()) {
if ( mainVersion > 0 ) {
String strMainPath = expPath + File.separator + "main." + mainVersion + "." + packageName + ".obb";
File main = new File(strMainPath);
if ( main.isFile() ) {
ret.add(strMainPath);
}
}
if ( patchVersion > 0 ) {
String strPatchPath = expPath + File.separator + "patch." + mainVersion + "." + packageName + ".obb";
File main = new File(strPatchPath);
if ( main.isFile() ) {
ret.add(strPatchPath);
}
}
}
String[] retArray = new String[ret.size()];
ret.toArray(retArray);
return retArray;
}
public static ZipResourceFile getResourceZipFile(String[] expansionFiles) throws IOException {
ZipResourceFile apkExpansionFile = null;
for (String expansionFilePath : expansionFiles) {
if ( null == apkExpansionFile ) {
apkExpansionFile = new ZipResourceFile(expansionFilePath);
} else {
apkExpansionFile.addPatchFile(expansionFilePath);
}
}
return apkExpansionFile;
}
public static ZipResourceFile getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion) throws IOException{
String[] expansionFiles = getAPKExpansionFiles(ctx, mainVersion, patchVersion);
return getResourceZipFile(expansionFiles);
}
}
上記のコメントスレッドに基づいて、ここで回答を提供します。問題は、LocalPath
が提供される方法です。 Androidでは、ファイルシステムパスは異なるメーカー間で一貫していないため、ストレージパスについて仮定する必要はありません。
だからこれではなく(単にサンプルコード):
public class MyActivity extends Activity {
static final String LocalPath = "/storage/emulated/0/Android/obb/com.company.productname/main.10003.com.company.productname.obb ";
...
}
あなたはこのようなことをする必要があります:
public class MyActivity extends Activity {
File mObb;
...
public void onCreate(Bundle savedInstanceState) {
super.onCreate();
...
mObb = new File(getObbDir(), getPackageName() + ".obb");
// Get the path for passing to UE4 later
String LocalPath = mObb.getAbsolutePath();
}
これにより、特定のデバイスのプライマリ外部ストレージで、アプリがアプリの正しいOBBの場所を取得できるようになります。その後、OBBをそこに保存し、後でアプリがUE4を起動したときに、ファイルを直接指すようにすることができます。
OBB(およびその他のファイル)のプライマリ外部ストレージ上のアプリの場所には、読み取りと書き込みの権限そのアプリの場合は必要ありません。外部ストレージのパスが上記の方法で生成されたパスではない場合、WRITE_EXTERNAL_STORAGE
データを書き込むには権限が必要です。