Android 6.0权限和安装OBB

我在Android 6.0及更高版本上遇到问题。

我正在使用的游戏是使用WRITE_EXTERNAL_STORAGE权限。 在Android 6.0及更高版本中,要求用户允许的警报必须显示。

我收到了一个摆脱这个警报的请求,这意味着游戏不能再使用WRITE_EXTERNAL_STORAGE了。

从技术上来说,游戏并不是在任何地方编写和阅读外部存储。 所有保存和caching的文件都存储在特定于应用程序的目录(/storage/emulated/0/Android/data/com.company.productname)中。但是,游戏必须读取(有时会下载)存储的OBB文件在/storage/emulated/0/Android/obb/com.company.productname目录下。

游戏可以访问这个目录,即使没有WRITE_EXTERNAL_STORAGE或READ_EXTERNAL_STORAGE设备:

  • 摩托罗拉Nexus 6
  • LG Nexus 5

但它似乎没有无法访问此目录:

  • 三星Galaxy S5,S6和S7
  • Nvidia Shield平板电脑

我已经检查过,即使使用阿尔法testing,以模拟从商店下载游戏。

当给予存储的权限(通过应用程序设置),然后一切运行良好。

OBB如何安装?

我使用的虚幻引擎4使用C open()函数来处理OBB文件:

int32 Handle = open(LocalPath, O_RDONLY); 

其中LocalPath是obb文件的完整path:/storage/emulated/0/Android/obb/com.company.productname/main.10003.com.company.productname.obb

问题是:

  1. 游戏是否需要读/写_EXTERNAL_STORAGE才能读取和下载OBB文件?
  2. 如果是的话,我怎么可能摆脱警告,要求用户的权限。
  3. 如果没有,那为什么三星Galaxy S系列会出现这样的麻烦?

Solutions Collecting From Web of "Android 6.0权限和安装OBB"

好的,这个问题似乎在其他地方被列出,但是我找不到,因为我不知道这是个确切的问题。

https://code.google.com/p/android/issues/detail?id=197287

由于某种原因,API23将OBB的用户设置为root用户,而不是正确的用户,因此应用程序无法访问它。

重新启动设备后,一切正常。

在这一点上,没有明确的解决方法。

感谢@Larry提供所有必要和有用的信息:)

请恳请您检查您的商店申请是否有书面许可。

感谢@Larry指出正确的解决scheme。

对于那些想知道的人来说,为什么AOSP APK扩展支持库不能在没有许可的情况下工作,这里是修改后的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中,不同制造商之间的文件系统path不一致,您不应该对存储path做任何假设。

所以,而不是有这个(只是例子代码):

 public class MyActivity extends Activity { static final String LocalPath = "/storage/emulated/0/Android/obb/com.company.productname/main.10003.com.company.p‌​roductname.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(和其他文件)的主外部存储上的应用程序位置不需要为该应用程序读取和写入的权限。 如果外部存储器上的path不是由上述方法生成的path,则需要WRITE_EXTERNAL_STORAGE权限才能写入数据。