Thursday, 10 January 2013

APK Expansion Files in Android with Example

Introduction

          Google Play currently requires that your APK file be no more than 50MB. For most applications, this is plenty of space for all the application's code and assets. However, some apps need more space for high-fidelity graphics, media files, or other large assets. Previously, if your app exceeded 50MB, you had to host and download the additional resources yourself when the user opens the app. Hosting and serving the extra files can be costly, and the user experience is often less than ideal. To make this process easier for you and more pleasant for users, Google Play allows you to attach two large expansion files that supplement your APK.

         Google Play hosts the expansion files for your application and serves them to the device at no cost to you. The expansion files are saved to the device's shared storage location (the SD card or USB-mountable partition; also known as the "external" storage) where your app can access them. On most devices, Google Play downloads the expansion file(s) at the same time it downloads the APK, so your application has everything it needs when the user opens it for the first time. In some cases, however, your application must download the files from Google Play when your application starts.

Overview

Each time you upload an APK using the Google Play Android Developer Console, you have the option to add one or two expansion files to the APK. Each file can be up to 2GB and it can be any format you choose, but we recommend you use a compressed file to conserve bandwidth during the download. Conceptually, each expansion file plays a different role:
  • The main expansion file is the primary expansion file for additional resources required by your application.
  • The patch expansion file is optional and intended for small updates to the main expansion file.

Screen: 
Please  see below screen for how apk expansion work. 



File name format

Each expansion file you upload can be any format you choose (ZIP, PDF, MP4, etc.).

[main|patch]...obb 
There are three components to this scheme:
 
 main or patch
Specifies whether the file is the main or patch expansion file. There can be only one main file and one patch file for each APK.

<expansion-version>
This is an integer that matches the version code of the APK with which the expansion is first associated.
Developer Console allows you to re-use an uploaded expansion file with a new APK,

<package-name>
Your application's Java-style package name.

For example, suppose your APK version is 314159 and your package name is com.example.app. If you upload a main expansion file, the file is renamed to:

main.314159.com.example.app.obb

Ex. main.1.packagename.obb.zip name used in my project.

Storage location

When Google Play downloads your expansion files to a device, it saves them to the system's shared storage location. To ensure proper behavior, you must not delete, move, or rename the expansion files. In the event that your application must perform the download from Google Play itself, you must save the files to the exact same location.

The specific location for your expansion files is:

<shared-storage>/Android/obb/<package-name>/

<shared-storage> is the path to the shared storage space, available from getExternalStorageDirectory().

<package-name> is your application's Java-style package name, available from getPackageName().

Ex: sdcard/Android/obb/packagename/main.1.packagename.obb

If you must unpack the contents of your expansion files, do not delete the .obb expansion files afterwards and do not save the unpacked data in the same directory
For example, we've provided a library project called the APK Expansion Zip Library that reads your data directly from the ZIP file.

Note: Unlike APK files, any files saved on the shared storage can be read by the user and other applications.

Download process

Most of the time, Google Play downloads and saves your expansion files at the same time it downloads the APK to the device. However, in some cases Google Play cannot download the expansion files or the user might have deleted previously downloaded expansion files. To handle these situations, your app must be able to download the files itself when the main activity starts, using a URL provided by Google Play.

The download process from a high level looks like this:
  1. User selects to install your app from Google Play.
  2. If Google Play is able to download the expansion files (which is the case for most devices), it downloads them along with the APK.
    If Google Play is unable to download the expansion files, it downloads the APK only.
  3. When the user launches your application, your app must check whether the expansion files are already saved on the device.
    1. If yes, your app is ready to go.
    2. If no, your app must download the expansion files over HTTP from Google Play. Your app must send a request to the Google Play client using the Google Play's Application Licensing service, which responds with the name, file size, and URL for each expansion file. With this information, you then download the files and save them to the proper storage location.
Caution: It is critical that you include the necessary code to download the expansion files from Google Play in the event that the files are not already on the device when your application starts. As discussed in the following section about Downloading the Expansion Files, we've made a library available to you that greatly simplifies this process and performs the download from a service with a minimal amount of code from you.

Use  Download Library to implement your download behavior. Its Very Easy to use & Implement Downloading behavior using Download Library. you can also take reference from Sample Demo App.

Downloading the Expansion files

In most cases, Google Play downloads and saves your expansion files to the device at the same time it installs or updates the APK. This way, the expansion files are available when your application launches for the first time. However, in some cases your app must download the expansion files itself by requesting them from a URL provided to you in a response from Google Play's Application Licensing service.

The basic logic you need to download your expansion files is the following:

1. When your application starts, look for the expansion files on the shared storage location (in the Android/obb/<package-name>/ directory).

a. If the expansion files are there, you're all set and your application can continue.

b. If the expansion files are not there:

1.) Perform a request using Google Play's Application Licensing to get your app's expansion file names, sizes, and URLs.

2.) Use the URLs provided by Google Play to download the expansion files and save the expansion files. You must save the files to the shared storage location (Android/obb/<package-name>/) and use the exact file name provided by Google Play's response.

Note:
The URL that Google Play provides for your expansion files is unique for every download and each one expires shortly after it is given to your application.

Note: Whether your application is free or not, Google Play returns the expansion file URLs only if the user acquired your application from Google Play.

Sample Demo App: 

You can Download Sample App from SDK Manager. And Take Reference from it.
You have to download below Library from SDK Manager in Eclipse.

Google Play Licensing Library

Google Play APK Expansion Library

Download from SDK Manager


You have to add total three Library in your Project for APK Expansion



1) APK Expansion Zip Library (SDK/extras/google/play_apk_expansion/zip_file)
2) Application Licensing (SDK/extras/google/market_licensing)
3) Downloader Library (SDK/extras/google/play_apk_expansion/downloader_library)

APK Expansion Zip Library 
This is an optional library that helps you read your expansion files when they're saved as ZIP files. Using this library allows you to easily read resources from your ZIP expansion files as a virtual file system.

Downloader Library
To use APK expansion files with your application and provide the best user experience with minimal effort on your behalf, we recommend you use the Downloader Library that's included in the Google Play APK Expansion Library package. This library downloads your expansion files in a background service, shows a user notification with the download status, handles network connectivity loss, resumes the download when possible, and more.

Application Licensing
If the files are not on the device, use Google Play's Application Licensing service to request URLs for the expansion files, then download and save them. 


Downloaded Sample Demo Available at below paths in your system.

ex. /Android SDK / extras/ google / play_apk_expansion/


 Declaring user permissions


    
    

    
    

    
    

    
    

    
    

    
    

Note:  By default, the Downloader Library requires API level 4, but the APK Expansion Zip Library requires API level 5. 

Implementing the downloader service

In order to perform downloads in the background, the Downloader Library provides its own Service subclass called DownloaderService that you should extend. In addition to downloading the expansion files for you, the DownloaderService also:

All you need to do is create a class in your application that extends the DownloaderService class and override three methods to provide specific application details:

getPublicKey()
 
This must return a string that is the Base64-encoded RSA public key for your publisher account, available from the profile page on the Developer Console (see Setting Up for Licensing).

getSALT()
 
This must return an array of random bytes that the licensing Policy uses to create an Obfuscator. The salt ensures that your obfuscated SharedPreferences file in which your licensing data is saved will be unique and non-discoverable.

getAlarmReceiverClassName()
 
This must return the class name of the BroadcastReceiver in your application that should receive the alarm indicating that the download should be restarted (which might happen if the downloader service unexpectedly stops).

For example, here's a complete implementation of DownloaderService:

public class SampleDownloaderService extends DownloaderService {
    // You must use the public key belonging to your publisher account

    public static final String BASE64_PUBLIC_KEY = "YourLVLKey";
    // You should also modify this salt
    public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98,
            -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84
    };

    @Override
    public String getPublicKey() {
        return BASE64_PUBLIC_KEY;
    }

    @Override
    public byte[] getSALT() {
        return SALT;
    }

    @Override
    public String getAlarmReceiverClassName() {
        return SampleAlarmReceiver.class.getName();
    }
}

Notice: You must update the BASE64_PUBLIC_KEY value to be the public key belonging to your publisher account. You can find the key in the Developer Console under your profile information. This is necessary even when testing your downloads.

Remember to declare the service in your manifest file:


    
    ...

 
 
Note: You have to add your BASE64 public key in  SampleDownloaderService in your app.
This key you can get when you create app in Google Market. 
 

Implementing the alarm receiver

In order to monitor the progress of the file downloads and restart the download if necessary, the DownloaderService schedules an RTC_WAKEUP alarm that delivers an Intent to a BroadcastReceiver in your application. You must define the BroadcastReceiver to call an API from the Downloader Library that checks the status of the download and restarts it if necessary.

You simply need to override the onReceive() method to call DownloaderClientMarshaller.startDownloadServiceIfRequired().

For example:

public class SampleAlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent,
                    SampleDownloaderService.class);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
    }
}
 
Notice that this is the class for which you must return the name in your
 service's getAlarmReceiverClassName() method (see the previous 
section). 
 
Remember to declare the receiver in your manifest file:
 

    
    ...

 
 

Activity for Expansion Handling

public class VideoDownloaderActivity extends Activity implements
        IDownloaderClient {


   /**
     * Here is where you place the data that the validator will use to determine
     * if the file was delivered correctly. This is encoded in the source code
     * so the application can easily determine whether the file has been
     * properly delivered without having to talk to the server. If the
     * application is using LVL for licensing, it may make sense to eliminate
     * these checks and to just rely on the server.
     */
    private static final XAPKFile[] xAPKS = { new XAPKFile(true, // true
                                                                    // signifies
                                                                    // a main
                                                                    // file
            1, // the version of the APK that the file was uploaded
                // against
            191696333L // the length of the file in bytes
    ),

 private class CopyTask extends AsyncTask<Void, Void, Boolean> {

        private ProgressDialog mProgressDialog;
        private Context context;

        public CopyTask(Context context) {
            this.context = context;

        }

        /**
         * Display the dialog first when the webservice call.
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            if (context != null) {
                mProgressDialog = ProgressDialog.show(context, "",
                        context.getString(R.string.copy_video_message), true,
                        false);

            }

        }

        /**
         * Call the webservice and parse the data from the service in
         * background.
         */
        @Override
        protected Boolean doInBackground(Void... params) {

            // return wsLinks.executeService(currentPage);
            for (XAPKFile xf : xAPKS) {

                String fileName = Helpers.getExpansionAPKFileName(
                        VideoDownloaderActivity.this, xf.mIsMain,
                        xf.mFileVersion);

                if (!Helpers.doesFileExist(VideoDownloaderActivity.this,
                        fileName, xf.mFileSize, false))
                    return true;
                fileName = Helpers.generateSaveFileName(
                        VideoDownloaderActivity.this, fileName);
                ZipResourceFile zrf;

                try {

                    zrf = APKExpansionSupport.getAPKExpansionZipFile(
                            VideoDownloaderActivity.this, 1, 0);

                    File path = new File(
                            Environment.getExternalStorageDirectory()
                                    + File.separator
                                    + getString(R.string.app_name));
                    if (!path.exists()) {
                        // create a File object for the
                        // parent directory
                        File photoDirectory = new File(
                                path.getAbsolutePath());
                        // have the object build the
                        // directory structure, if needed.
                        photoDirectory.mkdirs();
                    } else {
                        if (path.isDirectory()) {
                            String[] children = path.list();
                            Log.v(LOG_TAG, "file length:" + children.length);
                            for (int i = 0; i < children.length; i++) {
                                new File(path, children[i]).delete();
                            }
                        }

                    }

                    for (ZipEntryRO entry : zrf.getAllEntries()) {
                        Log.v(LOG_TAG, "name:" + entry.mFileName);
                        DataInputStream is = new DataInputStream(
                                zrf.getInputStream(entry.mFileName));
                        // AssetFileDescriptor af =
                        // zrf.getAssetFileDescriptor(entry.mFileName);
                        long length = entry.mCompressedLength;
                        byte[] buf = new byte[1024 * 256];
                        Log.v("assetfilediscripter", "" + length);
                        // FileOutputStream fos = new FileOutputStream("");

                        // OutputStream stream = new BufferedOutputStream(new
                        // FileOutputStream("/storage/sdcard0/Download/sample.mp3"));

                        String[] bits = entry.mFileName.split("/");
                        String lastOne = bits[bits.length-1];

                        Log.v(LOG_TAG, "path:" + path + ":"+ lastOne);

                        OutputStream stream = new BufferedOutputStream(
                                new FileOutputStream(path + "/" 
                                        + lastOne));
                        int bufferSize = 1024;
                        byte[] buffer = new byte[bufferSize];
                        int len = 0;
                        while ((len = is.read(buffer)) != -1) {
                            stream.write(buffer, 0, len);
                        }
                        if (stream != null)
                            stream.close();

                        // break;

                    }
                    return true;
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return false;

                }

            }
            return true;

        }

        /**
         * onPostExecute method after called webService and Set the data into
         * adapter after background task is complete. this method set footerView
         * into listView according to totalPAge.
         */
        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            if (mProgressDialog != null  && mProgressDialog.isShowing()) {
                mProgressDialog.dismiss();
            }

            if (result) {
                finish();
                Intent intent = new Intent(VideoDownloaderActivity.this,
                        VideoListActivity.class);
                startActivity(intent);
            } else {
                errorDialog(context, context.getString(R.string.copy_failed));
            }

        }

    }
}
 

Testing Your Expansion Files

Before publishing your application, there are two things you should test: Reading the expansion files and downloading the files.

Testing file reads

Before you upload your application to Google Play, you should test your application's ability to read the files from the shared storage. All you need to do is add the files to the appropriate location on the device shared storage and launch your application:

1.) On your device, create the appropriate directory on the shared storage where Google Play will save your files.

For example, if your package name is com.example.android, you need to create the directory Android/obb/com.example.android/ on the shared storage space. (Plug in your test device to your computer to mount the shared storage and manually create this directory.)

2.) Manually add the expansion files to that directory. Be sure that you rename your files to match the file name format that Google Play will use.

For example, regardless of the file type, the main expansion file for the com.example.android application should be main.0300110.com.example.android.obb. The version code can be whatever value you want. Just remember:
  • The main expansion file always starts with main and the patch file starts with patch.
  • The package name always matches that of the APK to which the file is attached on Google Play.
3.) Now that the expansion file(s) are on the device, you can install and run your application to test your expansion file(s).

Here are some reminders about handling the expansion files:
  • Do not delete or rename the .obb expansion files (even if you unpack the data to a different location). Doing so will cause Google Play (or your app itself) to repeatedly download the expansion file.
  • Do not save other data into your obb/ directory. If you must unpack some data, save it into the location specified by getExternalFilesDir().
Testing file download

Because your application must sometimes manually download the expansion files when it first opens, it's important that you test this process to be sure your application can successfully query for the URLs, download the files, and save them to the device.

To test your application's implementation of the manual download procedure, you must upload your application to Google Play as a "draft" to make your expansion files available for download:

1.) Upload your APK and corresponding expansion files using the Google Play Developer Console

2.) Fill in the necessary application details (title, screenshots, etc.). You can come back and finalize these details before publishing your application.

Click the Save button. Do not click Publish. This saves the application as a draft, such that your application is not published for Google Play users, but the expansion files are available for you to test the download process.

3.) Install the application on your test device using the Eclipse tools or adb.

4.) Launch the app.

If everything works as expected, your application should begin downloading the expansion files as soon as the main activity starts.


References: http://developer.android.com/google/play/expansion-files.html



57 comments:

  1. good post, thanks i have few issues like when i run the app it says

    02-21 03:05:04.782: E/AndroidRuntime(1483): FATAL EXCEPTION: main
    02-21 03:05:04.782: E/AndroidRuntime(1483): java.lang.NoClassDefFoundError: com.google.android.vending.licensing.APKExpansionPolicy
    02-21 03:05:04.782: E/AndroidRuntime(1483): at com.google.android.vending.expansion.downloader.impl.DownloaderService$LVLRunnable.run(DownloaderService.java:756)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at android.os.Handler.handleCallback(Handler.java:587)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at android.os.Handler.dispatchMessage(Handler.java:92)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at android.os.Looper.loop(Looper.java:130)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at android.app.ActivityThread.main(ActivityThread.java:3683)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at java.lang.reflect.Method.invokeNative(Native Method)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at java.lang.reflect.Method.invoke(Method.java:507)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    02-21 03:05:04.782: E/AndroidRuntime(1483): at dalvik.system.NativeStart.main(Native Method)

    what does this mean ?

    where am i going wrong

    ReplyDelete
    Replies
    1. Hello varun,

      had you added market_licensing library project in your project?

      if yes, remove library,clean it,add again library because class not found in your project.

      if no,market_licensing library available in your updated SDK (SDK/extras/google/market_licensing) Please add library project in your project.

      you have to add three library Project
      1)SDK/extras/google/play_apk_expansion/zip_file
      2)SDK/extras/google/play_apk_expansion/downloader_library
      3)SDK/extras/google/market_licensing

      Delete
    2. Thanks, Now its working but i ma not able to test it locally, i mean before uploading the apk file to android market.

      I have put the obb file in /Android/obb/package-name/my_obb_file

      But when i am testing it says "XAPK file Validation Failed"

      What might be the problem?

      Delete
    3. Hello varun,

      You have to comment APK Downloadig & Validation code & after that you have to Test it. This validateXAPKZipFiles() method Validate the expansion files so you have to comment it & Modify Some code for testing locally without uploading.

      Delete
    4. Hey, just wondering what did you have to modify and change to make it work locally. I'm in the same problem and could really do with some help :)

      Thank you!

      Josh

      Delete
    5. I like the helpful information you provide in your articles. I will bookmark your blog site and check again here regularly for best paid & latest Apps/Games
      Android Market Apk I'm quite certain & learn lots of new stuff right here!Best of luck for the next post. Thank u very much

      Delete
    6. Ankit can you please come on skype with me for few minutes?

      Delete
  2. Ankit Thakkar ,

    Thanks a lot, it works now,

    1) but i need to know are we extracting the data to some where here, i mean the data in the .obb file to some location in sdcard?.

    2)by using APK Expansion Zip Library i got to know that we can directly read the data from zip file only that is .obb file and we need not have to extract it.

    3) I have folder in the .obb file like birthdays, data in my .obb files and they are images ... how to read the data from there?

    ReplyDelete
  3. Nice post.Give it up. Thanks for share this article. For more visit:Web App Development

    ReplyDelete
  4. Nice post.Give it up. Thanks for share this article. For more visit:Web App Development

    ReplyDelete
  5. Hi Ankit Thakkar,

    Thanks for the explanation.

    I have project for which i want to implement the expansion files. Video and image files are in projects raw folder, i want to put the raw folder as an expansion file. And unable to implement the expansion file concept in my project.

    how to write the code to access the files from the shared storage into the application?
    can i zip all the available files together?




    ReplyDelete
    Replies
    1. Ok. Thank you so much for your quick reply. Let me try to implement.

      Delete
    2. Hi

      I have tried implementing expansion files into my application.Zipped raw folder and named it according to google doc.
      I have created a folder and placed the expansion file:
      android/obb/com.myappname/main.1.com.myappname.obb.zip

      now i have removed raw folder from the application.

      my code is as given below

      String path1 = "android.resource://" + getPackageName() + "/" + R.raw.e4;
      intent.putExtra ("FILE_PATH", path1);

      as soon as i remove raw folder from application, got the error under raw saying raw can't be resolved to a variable.

      how to overcome this issue .? how to change the code?



      Delete
    3. Hi Ankit Thakkar,

      Finally I have Implemented and launched my application. But i am seeing only black screen. and there are no errors in log cat or in the console.
      i do not know the reason for this. can you tell me the reason for this.

      Thanks

      Delete
    4. when i run the app in emulator i got the error as : " error opening the trace file: no such file or directory(2)

      Delete
  6. Hi Ankit Thakkar,

    I have tested the APK from Eclipse on my nexus 7.
    I have uploaded the APK and expansion files into google play and saved as draft.

    Now the App is downloading the expansion files from google play and saving on the device memory.

    now the problem is the code what i have written to access the .JPG and MP4 is not working. I need to research it.

    i do not know how to check the internal SD card folder on nexus 7.

    Please suggest me

    ReplyDelete
  7. hello,
    Hi i created one apk file, when i directly install in mobile its working correctly.
    if same time i upload same apk file in google play and my web page, that apk file can't able to download. its shows error...
    please give me the solution mail:adhamsheriff89@gmail.com...
    Thankyou.

    ReplyDelete
    Replies
    1. Hello

      If resource not found error occured, It takes sometime for downloading from google play. so you have to wait for it.

      You have to check in real device.

      Can i know which error gives?? So i can give you solution.

      Delete
  8. http://wininterview.blogspot.in/2013/04/download-file-in-android-from-remote.html

    ReplyDelete
  9. Hey Ankit Thakkar!

    Is there a standard way to deal with a situation when on app start the connection was off? I took the code from the downloader example from the SDK and and it worked good. But there's an issue I cannot solve and don't see any information on that.

    If the connection is off on the start of the application I get STATE_FAILED_FETCHING_URL in onDownloadStateChanged. And it cannot fetch the URL even after I switch the connection back.

    ReplyDelete
  10. Hi Ankit Thakkar,

    I am able to implement the expansion files now. Thanks a lot for the good explanation.

    But i have one small doubt. Will this app which has expansion files concept implemented is licensed app? I mean to say will it check for License always or do we need to implement it separately?

    ReplyDelete
    Replies
    1. Hello Chittee,

      This Library will check for License always so we don't need to implement it separately.

      Delete
    2. Hi Ankit Thakkar,

      That is great. Thanks a lot for the support and clarifications in implementing expansion files in my project.

      Delete
    3. Hi Chittee,

      How did you reference the media inside your expansion file?

      I am try to play video, can you please help me :)

      Thanks!

      Delete
    4. Hi Joshy Sav,

      Here is the code what i have implemented to reference the video files in the expansion files.
      Note: images is the folder name inside the zip under which i have all the video files.

      Below given is the method used in the class in which i want to refer the expansion fie. It should not in the oncreate method.


      public ZipResourceFile getExpansionFile() {

      String fileName = Helpers.getExpansionAPKFileName(this, true, 2);

      int filesize = 65966673;
      if (Helpers.doesFileExist(this, fileName, filesize, false)) {

      try {
      return APKExpansionSupport.getAPKExpansionZipFile(
      getBaseContext(), 2, 0);

      } catch (IOException e) {
      // TODO Auto-generated catch block

      e.printStackTrace();
      }
      }
      return null; }



      After getting the reference of video file using above method, i have played the video in another class using intent.

      here is the code:


      Intent intent = new Intent(getApplicationContext(), VideoDisplay.class);
      String videoname = "null";
      videoname = "images/a1.mp4";
      intent.putExtra("image",videoname);

      on the other end of the intent( the class in which the video is getting played).

      code is:

      Intent i = getIntent();
      Bundle bd = i.getExtras();
      String videopath = bd.getString("image");
      mVideoView.setVideoURI(Uri.parse(CONTENT_URI + "/" +videopath));
      mVideoView.setMediaController(new MediaController(this)); mVideoView.requestFocus();
      mVideoView.start();


      Hope it is clear.



      Delete
    5. Hello

      I am facing same issue like you. i have create one app using PhoneGap Android
      and i am plying video in that app and all the videos are in src/raw folder.
      so my app size is around 150 mb so please guide me
      what to do.
      actully java is new for me.

      Please Help me....

      Thanks in advance

      Delete
  11. HI..

    i have problem for my OBB files..
    i install *Iron Man 3* Game App with OBB files.. and then i install another Game App with OBB files.. my two games are remove.. the game is missing.. when i remove the OBB files for other game.. only 1 game are running then the rest are not.. please need some help..

    question.. how can i install 2 obb file for each games??..

    kolokoyjas@gmail.com send me.. please thanks..

    ReplyDelete
  12. Hello!
    Trying to split an apk with augmented reality via vuforia plugin, but keep getting this error:
    java.lang.Error: FATAL EXCEPTION [GLThread 11]
    Unity version : 4.1.5f1
    Device model : samsung GT-I9001
    Device fingerprint: samsung/GT-I9001/GT-I9001:2.3.4/GINGERBREAD/XXKP4:user/release-keys

    Caused by: java.lang.Error: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0000000c
    Build fingerprint: 'samsung/GT-I9001/GT-I9001:2.3.4/GINGERBREAD/XXKP4:user/release-keys'
    Revision: '0'
    pid: 29203, tid: 29212, name: UnityMain >>> com.OutsideReality.NuclearPlantAR <<<
    r0 00000007 r1 00000001 r2 00000000 r3 00000000
    r4 00000000 r5 40568b58 r6 002b3718 r7 4055dde8
    r8 47f52bc8 r9 47f53684 sl 47f5366c fp 47f52be8
    ip aca94d3c sp 47f52ba0 lr aca42d45 pc aca42d44 cpsr 0000000b

    at libdvm.00042d44(Native Method)
    at libunity.003fdf18(Native Method)
    at Unknown.000053f4(Unknown Source)
    at AndroidJNI.SetStaticStringField(Unknown Source)
    at AndroidJavaObject._SetStatic(<0x00378>:888)
    at AndroidJavaObject.SetStatic(<0x0003b>:59)
    at GooglePlayDownloader..cctor(<0x00097>:151)
    at Object.runtime_invoke_void(Unknown Source)
    at DownloadObbExample.OnGUI(Unknown Source)
    at DownloadObbExample.OnGUI(<0x00018>:24)
    at Object.runtime_invoke_void__this__(Unknown Source)
    at libmono.00023823(Native Method)
    at libmono.mono_runtime_invoke(mono_runtime_invoke:144)
    at libmono.mono_runtime_invoke(mono_runtime_invoke:56)
    at libunity.002d484c(Native Method)
    at libunity.002c7eb4(Native Method)
    at libunity.0022e110(Native Method)
    at libunity.0023cb8c(Native Method)
    at libunity.0023d7c8(Native Method)
    at libunity.002a547c(Native Method)
    at libunity.002a5dec(Native Method)
    at libunity.003b1c38(Native Method)
    at libunity.003b1cd8(Native Method)
    at libdvm.00011db4(Native Method)

    What could it be?

    ReplyDelete
  13. I'm struggling for days, but I have no idea what I'm doing wrong or what I did forget.

    I have downloaded the sampledownloaderactivity. Downloading the obb succeed.

    Then I want to download my own obb.
    I have uploaded a signed apk with an obb. No problem so far.
    - Then I changed the public key in the sample to the key of the apk
    - I changed the size of the obb and I change the package name.
    But the download failed. I have no idea what I did wrong or what I forget. I see that the sample has the right xapkfile what he wants to download.

    I hope someone has an idea.

    ReplyDelete
  14. I am getting the issue.
    download failed because resources could not be found.when download the apk from google play.
    I follow the following steps:-
    -Create a zip file as expansion file
    -Upload the apk in alpha test mode in google play
    -add expansion file with apk

    Thanks in advance!!
    Jagdish

    ReplyDelete
  15. I have the same problem with Google Play : "download failed because resources could not be found"

    ReplyDelete
  16. can you send me the source codeof the example ?

    ReplyDelete
  17. can you know me about how to create .obb file?

    ReplyDelete
  18. Hi Ankit,
    I saw your post.It is very nice.But i am little bit confused about expansion files.My app size is 56 MB play store not accepting that much of size so i want to implement expansion files for my app.Can u please help me.Thanks a lot in advance....

    ReplyDelete
  19. Hi can you please send me the source code of the example ? and how to add expansion file with apk?

    ReplyDelete
  20. Can you send source code of example ? please..my email id is raghuramidi@gmail.com

    ReplyDelete
  21. i need to remove a few obb files from the /android/obb folder as well as a copy of that obb off the SDcard, the files are write protected preventing me from deleting them, can you help me remove those files to reclaim the 400mb they are taking up?

    ReplyDelete
  22. Hi Ankit
    i have made 2 projects using expension files,i need to know whether it is necessary to keep byte[] salt unique or same for 2 projects??

    ReplyDelete
  23. Hi Ankit,
    If you have face the following problem , please suggest

    http://stackoverflow.com/questions/19835580/expansion-file-download-sample-not-showing-full-progress

    ReplyDelete
  24. Very nice article, well written, well explained, Thanks for sharing your knowledge with us, its really usefull for android developers.

    APK DATA DOWNLOAD

    ReplyDelete
  25. Dear Ankit, will you please upload the code/pckage for this project

    ReplyDelete
  26. Hi I'm having so much trouble with this I have set everything up abut the Helper.doesFileExist method keeps returning false. Even when I manually add the file to the Android/obb folder.

    ReplyDelete
  27. Hi Anit

    Is the code in your example enough to get this working or down we need to add more code from the sdk sample?

    ReplyDelete
  28. Hi Ankit,

    It is a nice post, It's clear my funda.

    ReplyDelete
  29. Yes give us full code. So we do it as you post.
    Lizenzagentur & Lizenzprodukt(e)

    ReplyDelete
  30. Hi Ankit,
    This post was very nice.But i am little bit confused about expansion files.My app size is more than 50 MB so play store was not accepting that much of size so i want to implement expansion files for my app.Can u please help me.Thanks a lot..........

    ReplyDelete
  31. Hi Ankit,

    I need help please. I am using Android Studio and I have made sure that libraries you mentioned are installed on Android SDK Manager. However, Android Studio cannot recognize DownloderService class

    Gradle: error: cannot find symbol class DownloaderService

    Also, DownloaderClientMarshaller

    Gradle: error: cannot find symbol variable DownloaderClientMarshaller

    Thank you in advance

    ReplyDelete
  32. Q: apparently in the past few days (?) something may have changed on the google-play side of things... as we've been unable to download content from an expansion APK for an app that is in "draft beta" status... seems that it must be in "published beta" status now in order for it's expansion-APK to be accessible from the app.

    Note in order to be able to toggle the app to "published beta", one must simply complete (or put placeholders in) for all of the required "meta-data" fields (e.g. images under the "Store Listing" and the legal checkboxes "Pricing & Distribution" sections).

    Anyways, curious if anyone else has run into this "change"... and hope this is helpful... :) cheers, --dk

    ReplyDelete
  33. Its simply superb.Feeling good to share the link to practice android interview questions @ http://skillgun.com

    ReplyDelete
  34. nice extension files on android version.. thanks for sharng..

    Top Android Apps|apk free apps

    ReplyDelete
  35. Thanks for nice tutorial

    I need complete example please send me zip file on
    kaushik.patel1991@gmail.com

    thanks

    ReplyDelete
  36. I like your post. It's very informative here you can find more tutorial about apk expansion

    visit here for smartphone details click here

    ReplyDelete
  37. your expansion and presentation is very nice i like the post thank you for sharing the blog..

    FCA authorization

    ReplyDelete