web-dev-qa-db-fra.com

Autorisations Android 6.0 et OBB de montage

J'ai un problème avec les autorisations sur Android 6.0 et supérieur.

Le jeu sur lequel je travaille utilisait l'autorisation WRITE_EXTERNAL_STORAGE. Sur Android 6.0 et les versions ultérieures, l'alerte demandant à un utilisateur de l'autoriser devait être affichée.

J'ai reçu une demande de suppression de cette alerte, ce qui signifie que le jeu ne peut plus utiliser WRITE_EXTERNAL_STORAGE.

Techniquement, le jeu n’écrit et ne lit pas le stockage externe n’importe où en ce moment. Tous les fichiers sauvegardés et mis en cache sont stockés dans le répertoire spécifique à l’application (/storage/emulated/0/Android/data/com.company.nomduproduit) Mais le jeu doit lire (et parfois télécharger) le fichier OBB qui est stocké dans le répertoire /storage/emulated/0/Android/obb/com.company.productname.

Le jeu a un accès à ce répertoire, même sans WRITE_EXTERNAL_STORAGE ni READ_EXTERNAL_STORAGE sur les appareils:

  • Motorola Nexus 6
  • LG Nexus 5

Mais il semble qu'il n'a pas d'accès à ce répertoire sur:

  • Samsung Galaxy S5, S6 et S7
  • Tablette Nvidia Shield

Je l'ai vérifié même en utilisant les tests alpha afin de simuler le téléchargement du jeu depuis le magasin.

Lorsque l'autorisation de stockage est donnée (via les paramètres de l'application), tout se passe bien.

Comment l'OBB est-il monté?

Le moteur Unreal Engine 4 que j'utilise utilise la fonction C open () pour gérer le fichier OBB:

int32 Handle = open(LocalPath, O_RDONLY);

Où LocalPath est un chemin d'accès complet au fichier obb: /storage/emulated/0/Android/obb/com.company.productname/main.10003.com.company.productname.obb

Les questions sont:

  1. Le jeu nécessite-t-il un _EXTERNAL_STORAGE READ/WRITE pour pouvoir lire et télécharger le fichier OBB?
  2. Si oui, comment puis-je éventuellement me débarrasser de l'alerte qui demande des autorisations à l'utilisateur?.
  3. Si non, alors pourquoi Samsung Galaxy S série faire de tels problèmes?
9
zompi

Ok, il semblerait que le problème ait été répertorié ailleurs, mais je n'ai pas pu le trouver car je ne savais pas que c'était le problème exact ...

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

Pour une raison quelconque, l’API23 définit l’utilisateur de l’OBB en tant qu’utilisateur root, et non l’utilisateur approprié; de ce fait, l’application n’y a pas accès.

Après le redémarrage de l'appareil, tout fonctionne bien.

À ce stade, il n'y a pas de solution de contournement claire pour cela.

Merci @Larry pour toutes les informations utiles et utiles :)

10
zompi

Vous êtes cordialement invité à vérifier si votre application du magasin dispose d'une autorisation d'écriture.

2
Ciprian Jijie

Merci à @ Larry pour avoir indiqué la bonne solution.

Pour ceux qui se demandent pourquoi le libray de support d'expansion d'AOSP APK ne fonctionne pas sans autorisation, voici le APKExpansionSupport.Java modifié

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);
    }
}
1
Dima Rostopira

Fournir une réponse ici basée sur le fil de commentaire ci-dessus. Le problème est la façon dont LocalPath est fourni. Sous Android, les chemins du système de fichiers ne sont pas cohérents entre les différents fabricants et vous ne devez faire aucune hypothèse concernant les chemins de stockage.

Donc plutôt que d'avoir ceci (juste un exemple de code):

public class MyActivity extends Activity {
    static final String LocalPath = "/storage/emulated/0/Android/obb/com.company.productname/main.10003.com.company.p‌​roductname.obb ";
    ...
}

Vous devez faire quelque chose comme ça:

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();
    }

Cela garantira que votre code obtiendra le bon emplacement OBB pour votre application sur le stockage externe principal pour le périphérique donné. Vous pouvez ensuite enregistrer l’OBB ici et plus tard, lorsque votre application démarrera UE4, elle pourra pointer directement vers le fichier.

L'emplacement d'une application sur le stockage externe principal pour OBB (et d'autres fichiers) ne nécessite pas d'autorisations de lecture et d'écriture pour cette application . Si le chemin sur le stockage externe n'est pas généré par les méthodes ci-dessus, l'autorisation WRITE_EXTERNAL_STORAGE est nécessaire pour écrire des données.

0
Larry Schiefer