Android 6.0 permissions and mounting OBB

15,013

Solution 1

Ok, it seems the issue was listed somewhere else, but I couldn't find because I didn't know it was the exact issue...

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

The API23 for some reason set's the user of the OBB to root, not the proper user and because of it the app has no access to it.

After rebooting the device everything works fine.

At this point there is no clear workaround for this.

Thanks @Larry for providing all necessary and helpful information :)

Solution 2

You are kindly invited to check if your application from store has writting permission.

Solution 3

Thanks to @Larry for pointing to right solution.

For those, who is wondering, why AOSP APK Expansion Support libray is not working without permission, here is the modified 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);
    }
}
Share:
15,013
zompi
Author by

zompi

Updated on July 19, 2022

Comments

  • zompi
    zompi almost 2 years

    I have a problem with permissions on Android 6.0 and higher.

    The game I'm working on was using the WRITE_EXTERNAL_STORAGE permission. On Android 6.0 and higher the alert which asks a user to allow it had to be displayed.

    I've received a request to get rid of this alert, which means, the game cannot use WRITE_EXTERNAL_STORAGE anymore.

    Technically the game is not writing and reading the external storage anywhere right now. All saves and cached files are stored in the application-specific directory (/storage/emulated/0/Android/data/com.company.productname) But, the game has to read (and sometimes download) the OBB file, which is stored in /storage/emulated/0/Android/obb/com.company.productname directory.

    The game has an access to this directory, even without WRITE_EXTERNAL_STORAGE or READ_EXTERNAL_STORAGE on devices:

    • Motorola Nexus 6
    • LG Nexus 5

    But it seems it doesn't have na access to this directory on:

    • Samsung Galaxy S5, S6 and S7
    • Nvidia Shield tablet

    I've checked it even using the Alpha Tests in order to simulate downloading the game from the store.

    When the permission to the Storage is given (via App Settings) then everything runs fine.

    How the OBB is mounted?

    The Unreal Engine 4, which I use, is using the C open() function to handle the OBB file:

    int32 Handle = open(LocalPath, O_RDONLY);
    

    Where LocalPath is a full path to the obb file: /storage/emulated/0/Android/obb/com.company.productname/main.10003.com.company.productname.obb

    The questions are:

    1. Does the game need a READ/WRITE _EXTERNAL_STORAGE in order to read and download OBB file?
    2. If yes, then how can I possibly get rid of the alert which asks the user for permissions.
    3. If no, then why Samsung Galaxy S series make such troubles?
  • zompi
    zompi almost 8 years
    Thanks for a tip, but still... I took the address using getObbDir() and getAbsolutePath() and it returned... /storage/emulated/0/Android/obb/com.company.productname ;) I also checked the errno from open method and it's EACCES 13 /* Permission denied */ There is also one thing... I install the game by putting apk and obb to the created directory in Android/obb and install APK. When I put Obb in root of storage and then copy it via inside Android File Manager to the proper directory and then install... then it works and has access...
  • Larry Schiefer
    Larry Schiefer almost 8 years
    Is the UE4 engine running within your app's process, or is it a separate component / package?
  • Larry Schiefer
    Larry Schiefer almost 8 years
    OK, it sounds very odd what you're doing to install the app and obb file. The app installation should be done via adb or the play store, so no special storage location needed. Typically your obb file(s) are downloaded by the app and placed into the obb directory or you can host them on Google Play and pull them down in that way. The framework needs to be the thing that creates the obb directory, so the APK must be installed first so permissions get setup correctly. If you are manually creating the directory (adb shell?) then trying to use it, that will cause problems.
  • zompi
    zompi almost 8 years
    UE4 engine is running within the app (it means the engine and the game is the same entity). What's more mystarious, I've checked the file with getExternalStorageState and received MEDIA_MOUNTED as result. So... it should be accessible, but not via C open? :/ I was also installing the app via Alpha Tests and the same problem occurs.
  • zompi
    zompi almost 8 years
    Ok, so I've installed the apk via adb and then simply put the obb to the created by application directory in Android/obb. And now it works... But why it didn't work when the game was installed via Alpha Test from Google Store? :(
  • Larry Schiefer
    Larry Schiefer almost 8 years
    It should be OK if created by install from the play store or adb and you're using the getObbDir() method. If using the constant string it will fail on some devices as the mount points differ.
  • zompi
    zompi almost 8 years
    After quite a long search I found the issue here code.google.com/p/android/issues/detail?id=197287 and here comments.gmane.org/gmane.comp.handhelds.android.devel/244716 and I can confirm that the user of the installed app i root not the user.