com.tealeaf.ResourceDownloaderTask.java Source code

Java tutorial

Introduction

Here is the source code for com.tealeaf.ResourceDownloaderTask.java

Source

/* @license
 * This file is part of the Game Closure SDK.
 *
 * The Game Closure SDK is free software: you can redistribute it and/or modify
 * it under the terms of the Mozilla Public License v. 2.0 as published by Mozilla.
    
 * The Game Closure SDK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * Mozilla Public License v. 2.0 for more details.
    
 * You should have received a copy of the Mozilla Public License v. 2.0
 * along with the Game Closure SDK.  If not, see <http://mozilla.org/MPL/2.0/>.
 */
package com.tealeaf;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Iterator;

import org.json.JSONException;
import org.json.JSONObject;

import com.tealeaf.test_app.TestAppActivity;
import com.tealeaf.util.HTTP;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.os.AsyncTask;
import android.widget.Toast;

public class ResourceDownloaderTask extends AsyncTask<Activity, Float, Boolean> {
    private String host;
    private int port;
    private AppInfo appInfo;
    private ProgressDialog progressDialog;
    private Activity context;
    private String lastFilename;
    private boolean errorDownloading;

    public ResourceDownloaderTask(Activity context, String host, int port, AppInfo appInfo) {
        this.host = host;
        this.port = port;
        this.appInfo = appInfo;
        this.progressDialog = new ProgressDialog(context);
        this.progressDialog.setProgressStyle(1); //horizontal
        this.progressDialog.setMax(100);
        this.context = context;
        this.lastFilename = null;
        this.errorDownloading = false;

    }

    @Override
    protected Boolean doInBackground(Activity... params) {
        lastFilename = null;
        //get options and resource manager
        TeaLeafOptions opts = new TeaLeafOptions();
        opts.setAppID(appInfo.appid);
        final ResourceManager resourceManager = new ResourceManager(params[0], opts);
        //get the storage directory
        final String storageDir = resourceManager.getStorageDirectory();
        File storage = new File(storageDir);
        //assure storage directory folders are there
        if (!storage.exists()) {
            storage.mkdirs();
        }

        HTTP http = new HTTP();

        // get the file containing the hashes of the last download if it exists
        File hashFile = new File(storageDir + "/resource_list.json");
        JSONObject prevHashes = new JSONObject();
        if (hashFile.exists()) {
            String hashFileString = fileToString(hashFile);
            try {
                prevHashes = new JSONObject(hashFileString);
            } catch (JSONException e) {
                logger.log(e);
            }
        }

        //form the simulate url
        String simulateUrl = "http://" + host + ":" + port + "/simulate/debug/" + appInfo.id + "/native-android/";

        //first get native.js
        String url = simulateUrl + "native.js";
        http = new HTTP();
        String nativejsPath = storageDir + "/" + "native.js";
        http.getFile(URI.create(url), nativejsPath);

        //get loading.png
        url = simulateUrl + "splash/portrait960";
        String loadingPngPath = storageDir + "/" + "loading.png";
        File splash = http.getFile(URI.create(url), loadingPngPath);
        //try again if we couldn't find the higher res splash
        if (splash == null || !splash.exists()) {
            url = simulateUrl + "splash/portrait480";
            http.getFile(URI.create(url), loadingPngPath);
        }

        HashMap<String, String> requestHeaders = new HashMap<String, String>();
        //get new resource list
        String body = null;
        int retry = 3;
        while (retry-- > 0) {
            url = simulateUrl + "resource_list.json";
            body = http.get(URI.create(url));
            if (body != null && !body.equals("")) {
                break;
            }
        }

        JSONObject serverHashes = null;
        try {
            // loop through all resources and download any
            // that we don't have cached locally
            serverHashes = new JSONObject(body);
            int numFiles = serverHashes.length();

            @SuppressWarnings("unchecked") // using legacy API, remove warning
            Iterator<String> files = serverHashes.keys();

            publishProgress(1.f, 1.f, (float) numFiles);

            http = new HTTP();
            int currentFile = 0;
            while (files.hasNext()) {
                String filePath = files.next();
                lastFilename = filePath;
                if (filePath.contains("native.js")) {
                    continue;
                }

                String fullPath = storageDir + "/" + filePath;

                // need to get the directory this file is in and create it
                File fullPathFile = new File(fullPath);
                new File(fullPathFile.getParent() + "/").mkdirs();

                // check if there is a previous hash
                String prevHash = null;
                try {
                    prevHash = (String) prevHashes.get(filePath);
                } catch (JSONException e) {
                    // expected to happen first load
                    logger.log(e);
                }

                // check if the server hash is a match
                boolean cached = false;
                try {
                    String hash = (String) serverHashes.get(filePath);
                    if (hash != null && hash.equals(prevHash)) {
                        cached = true;
                    }
                } catch (JSONException e) {
                    // oh well, just download it!
                }

                if (!cached || !(new File(fullPath).exists())) {
                    // get the file and cache it to disk
                    url = "http://" + host + ":" + port + "/simulate/debug/" + appInfo.id + "/native-android/"
                            + filePath;
                    url = url.replace(" ", "%20");
                    http.getFile(URI.create(url), fullPath, requestHeaders);
                }

                // update progress
                publishProgress(1.f, (float) ++currentFile, (float) numFiles);
                ;
            }
        } catch (Exception e) {
            logger.log("broken!");
            logger.log("error is", e);
            errorDownloading = true;
            cancel(true);
            logger.log(e);
        }

        if (serverHashes != null) {
            stringToFile(hashFile, serverHashes.toString());
        }

        return true;
    }

    private String fileToString(final File file) {
        StringBuilder result = new StringBuilder();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            char[] buf = new char[1024];
            int r = 0;
            while ((r = reader.read(buf)) != -1) {
                result.append(buf, 0, r);
            }
        } catch (Exception e) {
            logger.log(e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    logger.log(e);
                }
            }
        }

        return result.toString();
    }

    private void stringToFile(File file, String content) {

        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(file);
            fileWriter.write(content);
            fileWriter.close();
        } catch (IOException e) {
            logger.log(e);
        } finally {
            try {
                fileWriter.close();
            } catch (IOException e) {
                logger.log(e);
            }
        }
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        this.progressDialog.setMessage("running basil build...");
        this.progressDialog.setOnCancelListener(new OnCancelListener() {
            public void onCancel(DialogInterface dialog) {
                ResourceDownloaderTask.this.cancel(true);
            }
        });
        this.progressDialog.show();

    }

    @Override
    protected void onProgressUpdate(Float... values) {
        super.onProgressUpdate(values);
        if (values[0].intValue() == 1) {
            this.progressDialog.setMessage("downloading resources...");
        }
        this.progressDialog.setMax(values[2].intValue());
        this.progressDialog.setProgress(values[1].intValue());
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();
        this.progressDialog.dismiss();
        String message = "downloading cancelled. try again!";
        Toast.makeText(this.context, message, Toast.LENGTH_LONG).show();
        if (errorDownloading && lastFilename != null) {
            errorDownloading = false;
            message = "\nError downloading " + lastFilename + ".";
            Toast.makeText(this.context, message, Toast.LENGTH_LONG).show();
        }
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        this.progressDialog.dismiss();
        Toast.makeText(this.context, "launching game...", Toast.LENGTH_LONG).show();
        ((TestAppActivity) context).launchDebugApp();
    }
}