2

First of all. Read all before giving down vote.

I am trying to achieve one of biggest challange for me that download OBB file through google market. I have tested/tried almost every single code published in here and read almost every single topic which posted here unfortunately non-of-them solved my problem.

What i did so far? well, i have import sample download activity from SDK directory and changed it to my APP which is currently publishing in Market also created an OBB file and uploaded it and saved it in DRAFT mode.

So, i have followed tutorial in http://my.fit.edu/~vkepuska/ece5570/adt-bundle-windows-x86_64/sdk/docs/guide/google/play/expansion-files.html step by step. My test APP shows up but download is not starting.

This is my BroadcastReceiver:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;

import com.google.android.vending.expansion.downloader.DownloaderClientMarshaller;

public class DownloadFinished extends BroadcastReceiver
{
    @Override
    public void onReceive(Context arg0, Intent arg1)
    {
        try
        {
            DownloaderClientMarshaller.startDownloadServiceIfRequired(arg0, arg1, SampleDownloaderService.class);
        }
        catch (NameNotFoundException e)
        {
            e.printStackTrace();
        }
    }
}

And this is my DownloaderService:

import com.google.android.vending.expansion.downloader.impl.DownloaderService;

public class SampleDownloaderService extends DownloaderService
{
    private static final String BASE64_PUBLIC_KEY   = "MIIBIjANBgkqhkiG9w0BAQE..........";
    private static final byte[] SALT                = new byte[]{1, 43, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -108, -33, 45, -1, 84};

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

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

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

And this is my Activity:

public class SplashActivity extends Activity implements IDownloaderClient
{
    // OBB DOWNLOAD
    static private final XAPKFile[] xAPKS               = {new XAPKFile(true, 5, 58814844L)};
    static private final float      SMOOTHING_FACTOR    = 0.005f;
    private IStub                   mDownloaderClientStub;
    private IDownloaderService      mRemoteService;
    private View                    mDashboard;
    private View                    mCellMessage;
    private ProgressBar             mPB;

    private TextView                mStatusText;
    private TextView                mProgressFraction;
    private TextView                mProgressPercent;
    private TextView                mAverageSpeed;
    private TextView                mTimeRemaining;
    private Button                  mPauseButton;
    private Button                  mWiFiSettingsButton;

    private boolean                 mCancelValidation;
    private boolean                 mStatePaused;
    private int                     mState;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        initializeDownloadUI();

        if (!expansionFilesDelivered())
        {
            try
            {
                Intent launchIntent = SplashActivity.this.getIntent();
                Intent i = new Intent(SplashActivity.this, SplashActivity.this.getClass());
                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                i.setAction(launchIntent.getAction());

                if (launchIntent.getCategories() != null)
                    for (String category : launchIntent.getCategories())
                        i.addCategory(category);

                // Build PendingIntent used to open this activity from
                // Notification
                PendingIntent pendingIntent = PendingIntent.getActivity(SplashActivity.this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
                // Request to start the download
                int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SplashActivity.class);

                if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED)
                {
                    // The DownloaderService has started downloading the files,
                    // show progress
                    initializeDownloadUI();
                    return;
                } // otherwise, download not needed so we fall through to
                    // starting the movie
            }
            catch (NameNotFoundException e)
            {
                // Log.e(LOG_TAG, "Cannot find own package! MAYDAY!");
                e.printStackTrace();
            }
        }
        else
            validateXAPKZipFiles();
    }

    @Override
    protected void onStop()
    {
        if (null != mDownloaderClientStub)
            mDownloaderClientStub.disconnect(this);

        super.onStop();
    }

    @Override
    protected void onStart()
    {
        if (null != mDownloaderClientStub)
            mDownloaderClientStub.connect(this);

        super.onStart();
    }

    @Override
    protected void onDestroy()
    {
        this.mCancelValidation = true;
        super.onDestroy();
    }

    @Override
    public void onServiceConnected(Messenger m)
    {
        mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
        mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
    }

    @Override
    public void onDownloadStateChanged(int newState)
    {
        setState(newState);
        boolean showDashboard = true;
        boolean showCellMessage = false;
        boolean paused;
        boolean indeterminate;

        switch (newState)
        {
            case IDownloaderClient.STATE_IDLE :
                // STATE_IDLE means the service is listening, so it's
                // safe to start making calls via mRemoteService.
                paused = false;
                indeterminate = true;
                break;
            case IDownloaderClient.STATE_CONNECTING :
            case IDownloaderClient.STATE_FETCHING_URL :
                showDashboard = true;
                paused = false;
                indeterminate = true;
                break;
            case IDownloaderClient.STATE_DOWNLOADING :
                paused = false;
                showDashboard = true;
                indeterminate = false;
                break;
            case IDownloaderClient.STATE_FAILED_CANCELED :
            case IDownloaderClient.STATE_FAILED :
            case IDownloaderClient.STATE_FAILED_FETCHING_URL :
            case IDownloaderClient.STATE_FAILED_UNLICENSED :
                paused = true;
                showDashboard = false;
                indeterminate = false;
                break;
            case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION :
            case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION :
                showDashboard = false;
                paused = true;
                indeterminate = false;
                showCellMessage = true;
                break;
            case IDownloaderClient.STATE_PAUSED_BY_REQUEST :
                paused = true;
                indeterminate = false;
                break;
            case IDownloaderClient.STATE_PAUSED_ROAMING :
            case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE :
                paused = true;
                indeterminate = false;
                break;
            case IDownloaderClient.STATE_COMPLETED :
                showDashboard = false;
                paused = false;
                indeterminate = false;
                validateXAPKZipFiles();
                return;
            default :
                paused = true;
                indeterminate = true;
                showDashboard = true;
        }

        int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE;

        if (mDashboard.getVisibility() != newDashboardVisibility)
            mDashboard.setVisibility(newDashboardVisibility);

        int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE;

        if (mCellMessage.getVisibility() != cellMessageVisibility)
            mCellMessage.setVisibility(cellMessageVisibility);

        mPB.setIndeterminate(indeterminate);
        setButtonPausedState(paused);
    }

    @Override
    public void onDownloadProgress(DownloadProgressInfo progress)
    {
        mAverageSpeed.setText(getString(R.string.kilobytes_per_second, Helpers.getSpeedString(progress.mCurrentSpeed)));
        mTimeRemaining.setText(getString(R.string.time_remaining, Helpers.getTimeRemaining(progress.mTimeRemaining)));

        progress.mOverallTotal = progress.mOverallTotal;
        mPB.setMax((int) (progress.mOverallTotal >> 8));
        mPB.setProgress((int) (progress.mOverallProgress >> 8));
        mProgressPercent.setText(Long.toString(progress.mOverallProgress * 100 / progress.mOverallTotal) + "%");
        mProgressFraction.setText(Helpers.getDownloadProgressString(progress.mOverallProgress, progress.mOverallTotal));
    }

    private void initializeDownloadUI()
    {
        mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SplashActivity.class);
        setContentView(R.layout.splash_screen);

        mPB = (ProgressBar) findViewById(R.id.progressBar);
        mStatusText = (TextView) findViewById(R.id.statusText);
        mProgressFraction = (TextView) findViewById(R.id.progressAsFraction);
        mProgressPercent = (TextView) findViewById(R.id.progressAsPercentage);
        mAverageSpeed = (TextView) findViewById(R.id.progressAverageSpeed);
        mTimeRemaining = (TextView) findViewById(R.id.progressTimeRemaining);
        mDashboard = findViewById(R.id.downloaderDashboard);
        mCellMessage = findViewById(R.id.approveCellular);
        mPauseButton = (Button) findViewById(R.id.pauseButton);
        mWiFiSettingsButton = (Button) findViewById(R.id.wifiSettingsButton);

        mPauseButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                if (mStatePaused)
                    mRemoteService.requestContinueDownload();
                else
                    mRemoteService.requestPauseDownload();

                setButtonPausedState(!mStatePaused);
            }
        });

        mWiFiSettingsButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
            }
        });

        Button resumeOnCell = (Button) findViewById(R.id.resumeOverCellular);
        resumeOnCell.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view)
            {
                mRemoteService.setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
                mRemoteService.requestContinueDownload();
                mCellMessage.setVisibility(View.GONE);
            }
        });
    }

    void validateXAPKZipFiles()
    {
        AsyncTask<Object, DownloadProgressInfo, Boolean> validationTask = new AsyncTask<Object, DownloadProgressInfo, Boolean>()
        {
            @Override
            protected void onPreExecute()
            {
                mDashboard.setVisibility(View.VISIBLE);
                mCellMessage.setVisibility(View.GONE);
                mStatusText.setText(R.string.text_verifying_download);
                mPauseButton.setOnClickListener(new View.OnClickListener()
                {
                    @Override
                    public void onClick(View view)
                    {
                        mCancelValidation = true;
                    }
                });
                mPauseButton.setText(R.string.text_button_cancel_verify);
                super.onPreExecute();
            }

            @Override
            protected Boolean doInBackground(Object... params)
            {
                for (XAPKFile xf : xAPKS)
                {
                    String fileName = Helpers.getExpansionAPKFileName(SplashActivity.this, xf.mIsMain, xf.mFileVersion);

                    if (!Helpers.doesFileExist(SplashActivity.this, fileName, xf.mFileSize, false))
                        return false;

                    fileName = Helpers.generateSaveFileName(SplashActivity.this, fileName);
                    ZipResourceFile zrf;
                    byte[] buf = new byte[1024 * 256];

                    try
                    {
                        zrf = new ZipResourceFile(fileName);
                        ZipEntryRO[] entries = zrf.getAllEntries();
                        /**
                         * First calculate the total compressed length
                         */
                        long totalCompressedLength = 0;

                        for (ZipEntryRO entry : entries)
                            totalCompressedLength += entry.mCompressedLength;

                        float averageVerifySpeed = 0;
                        long totalBytesRemaining = totalCompressedLength;
                        long timeRemaining;
                        /**
                         * Then calculate a CRC for every file in the Zip file,
                         * comparing it to what is stored in the Zip directory.
                         * Note that for compressed Zip files we must extract
                         * the contents to do this comparison.
                         */
                        for (ZipEntryRO entry : entries)
                        {
                            if (-1 != entry.mCRC32)
                            {
                                long length = entry.mUncompressedLength;
                                CRC32 crc = new CRC32();
                                DataInputStream dis = null;

                                try
                                {
                                    dis = new DataInputStream(zrf.getInputStream(entry.mFileName));

                                    long startTime = SystemClock.uptimeMillis();

                                    while (length > 0)
                                    {
                                        int seek = (int) (length > buf.length ? buf.length : length);
                                        dis.readFully(buf, 0, seek);
                                        crc.update(buf, 0, seek);
                                        length -= seek;
                                        long currentTime = SystemClock.uptimeMillis();
                                        long timePassed = currentTime - startTime;

                                        if (timePassed > 0)
                                        {
                                            float currentSpeedSample = (float) seek / (float) timePassed;

                                            if (0 != averageVerifySpeed)
                                                averageVerifySpeed = SMOOTHING_FACTOR * currentSpeedSample + (1 - SMOOTHING_FACTOR) * averageVerifySpeed;
                                            else
                                                averageVerifySpeed = currentSpeedSample;

                                            totalBytesRemaining -= seek;
                                            timeRemaining = (long) (totalBytesRemaining / averageVerifySpeed);
                                            this.publishProgress(new DownloadProgressInfo(totalCompressedLength, totalCompressedLength - totalBytesRemaining,
                                                    timeRemaining, averageVerifySpeed));
                                        }

                                        startTime = currentTime;

                                        if (mCancelValidation)
                                            return true;
                                    }

                                    if (crc.getValue() != entry.mCRC32)
                                    {
                                        System.out.println("CRC does not match for entry: " + entry.mFileName);
                                        System.out.println("In file: " + entry.getZipFileName());
                                        return false;
                                    }
                                }
                                finally
                                {
                                    if (null != dis)
                                        dis.close();
                                }
                            }
                        }
                    }
                    catch (IOException e)
                    {
                        e.printStackTrace();
                        return false;
                    }
                }
                return true;
            }

            @Override
            protected void onProgressUpdate(DownloadProgressInfo... values)
            {
                onDownloadProgress(values[0]);
                super.onProgressUpdate(values);
            }

            @Override
            protected void onPostExecute(Boolean result)
            {
                mDashboard.setVisibility(View.VISIBLE);
                mCellMessage.setVisibility(View.GONE);

                if (result)
                {
                    mStatusText.setText(R.string.text_validation_complete);
                    mPauseButton.setText(android.R.string.ok);
                }
                else
                {
                    mStatusText.setText(R.string.text_validation_failed);
                    mPauseButton.setText(android.R.string.cancel);
                }

                mPauseButton.setOnClickListener(new View.OnClickListener()
                {
                    @Override
                    public void onClick(View view)
                    {
                        finish();
                    }
                });

                super.onPostExecute(result);
            }
        };

        validationTask.execute(new Object());
    }

    boolean expansionFilesDelivered()
    {
        for (XAPKFile xf : xAPKS)
        {
            String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsMain, xf.mFileVersion);
            if (!Helpers.doesFileExist(this, fileName, xf.mFileSize, false))
                return false;
        }
        return true;    // Always return true;
    }

    private static class XAPKFile
    {
        public final boolean    mIsMain;
        public final int        mFileVersion;
        public final long       mFileSize;

        XAPKFile(boolean isMain, int fileVersion, long fileSize)
        {
            mIsMain = isMain;
            mFileVersion = fileVersion;
            mFileSize = fileSize;
        }
    }

    private void setButtonPausedState(boolean paused)
    {
        mStatePaused = paused;
        int stringResourceID = paused ? R.string.text_button_resume : R.string.text_button_pause;
        mPauseButton.setText(stringResourceID);
    }

    private void setState(int newState)
    {
        if (mState != newState)
        {
            mState = newState;
            mStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState));
        }
    }
}

I really appreciate if someone shows me right direction.

EDIT : I am not sure this output is related with my problem 12-08 11:15:12.431: D/OpenGLRenderer(27491): Enabling debug mode 0 12-08 11:15:42.273: D/libEGL(28577): loaded /system/lib/egl/libEGL_adreno200.so 12-08 11:15:42.274: D/libEGL(28577): loaded /system/lib/egl/libGLESv1_CM_adreno200.so 12-08 11:15:42.276: D/libEGL(28577): loaded /system/lib/egl/libGLESv2_adreno200.so

But this is definitely related when i hit back button 12-08 11:18:58.396: E/ActivityThread(28577): Activity com.sample.downloadobb.SplashActivity has leaked ServiceConnection com.google.android.vending.expansion.downloader.DownloaderClientMarshaller$Stub$2@411c1e40 that was originally bound here 12-08 11:18:58.396: E/ActivityThread(28577): android.app.ServiceConnectionLeaked: Activity com.sample.downloadobb.SplashActivity has leaked ServiceConnection com.google.android.vending.expansion.downloader.DownloaderClientMarshaller$Stub$2@411c1e40 that was originally bound here 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.LoadedApk$ServiceDispatcher.(LoadedApk.java:974) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:868) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.ContextImpl.bindService(ContextImpl.java:1462) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.ContextImpl.bindService(ContextImpl.java:1451) 12-08 11:18:58.396: E/ActivityThread(28577): at android.content.ContextWrapper.bindService(ContextWrapper.java:473) 12-08 11:18:58.396: E/ActivityThread(28577): at com.google.android.vending.expansion.downloader.DownloaderClientMarshaller$Stub.connect(DownloaderClientMarshaller.java:177) 12-08 11:18:58.396: E/ActivityThread(28577): at com.sample.downloadobb.SplashActivity.onStart(SplashActivity.java:113) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1164) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.Activity.performStart(Activity.java:5114) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2272) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.ActivityThread.access$600(ActivityThread.java:167) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1276) 12-08 11:18:58.396: E/ActivityThread(28577): at android.os.Handler.dispatchMessage(Handler.java:99) 12-08 11:18:58.396: E/ActivityThread(28577): at android.os.Looper.loop(Looper.java:137) 12-08 11:18:58.396: E/ActivityThread(28577): at android.app.ActivityThread.main(ActivityThread.java:5158) 12-08 11:18:58.396: E/ActivityThread(28577): at java.lang.reflect.Method.invokeNative(Native Method) 12-08 11:18:58.396: E/ActivityThread(28577): at java.lang.reflect.Method.invoke(Method.java:511) 12-08 11:18:58.396: E/ActivityThread(28577): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 12-08 11:18:58.396: E/ActivityThread(28577): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 12-08 11:18:58.396: E/ActivityThread(28577): at dalvik.system.NativeStart.main(Native Method)

0 Answers0