Mark Harrop Mark Harrop - 3 months ago 10
Android Question

How to make a super class I can call to handle my downloads

I'm really struggling with my DropBox API.

I want to have it in a super class that I can call from other classes.

What is confusing me is the fact I don't know how to set it up properly.

I've made the class and declared it a super class.

I've got all my API info in, but I need to be able to pick the name of the folder and file name from a different activity.

I.e.: I have a section called launchers and that section has 7 options for downloading; then I have another Activity with 3 downloads called anima and I want to use the same API just change the dir and path.

Also how would I then call it from another Activity?

public class HarropDropBoxApi extends Activity {

public static String APP_TYPE = "I want to name this from other classes??";
public static String APK_NAME = "I want to name this depending on the item in my list view in other classes ";
public static String path = Environment.getExternalStorageDirectory().getAbsolutePath() + APP_TYPE;
public static File Dir = new File(path);
AndroidAuthSession session = buildSession();


static DropboxAPI<AndroidAuthSession> dropboxAPI;
private final String APP_KEY = "my-app-key";
private final String APP_ACCESS = "my-access-key";
private final String TOKEN = "my-token";
private DropboxAPI.UploadRequest request;

public HarropDropBoxApi() {


}

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

Dir.mkdir();

dropboxAPI = new DropboxAPI<AndroidAuthSession>(session);
//below was how i was calling the api for a single App Type and Apk name
//DownloadFromDropboxFromPath(path + "downloadFileFromDropbox", "CastingApps/AllCast.apk");

/// This line ive changed to match my strings above to be called from other classes/activities will this work?
// Also this line is where the file is downloaded to and from so does this line get called from here or from my activities??
DownloadFromDropboxFromPath(path + "downloadFileFromDropbox", APP_TYPE + APK_NAME );

}

private AndroidAuthSession buildSession() {
AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_ACCESS);
AndroidAuthSession session = new AndroidAuthSession(appKeyPair);
session.setOAuth2AccessToken(TOKEN);
return session;
}

public static String DropboxDownloadPathFrom = "";
public static String DropboxDownloadPathTo = "";

private void DownloadFromDropboxFromPath(String downloadPathTo, final String downloadPathFrom) {
DropboxDownloadPathTo = downloadPathTo;
DropboxDownloadPathFrom = downloadPathFrom;

runOnUiThread(new Runnable() {
@Override
public void run() {

Toast.makeText(getApplicationContext(), "Downloading Please wait ...", Toast.LENGTH_LONG).show();
Thread th = new Thread(new Runnable() {
public void run() {
final File file = new File(DropboxDownloadPathTo + DropboxDownloadPathFrom.substring(DropboxDownloadPathFrom.lastIndexOf('.')));
if (file.exists()) file.delete();


try {
FileOutputStream outputStream = new FileOutputStream(file);
HarropDropBoxApi.dropboxAPI.getFile(DropboxDownloadPathFrom, null, outputStream, null);
getMain().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "File successfully downloaded.", Toast.LENGTH_SHORT).show();





Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(Uri.fromFile(file),
"application/vnd.android.package-archive");
promptInstall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(promptInstall);

}
});
} catch (Exception e) {
e.printStackTrace();
}

}
});
th.start();
}
});
}


public HarropDropBoxApi getMain() {
return this;
}
}

Answer

Since I am not using the Dropbox API, I put together this without testing it, but the logic seems good to me.

First, use an AsyncTask, not a low-level Thread for background operations. Things to note here:

  1. You give a Context parameter (like an Activity) with the expectation that you move the hard-coded strings out of the Java code and into some resource file.
  2. An interface callback has been added so that you can return the result back to the place this task was executed. Without calling setOnDownloadListener, the file will download, but nothing will happen as a result.
  3. (Additional note): It would appear you could hard-code a directory that always exists; there is no need to specify a "download to" directory.
public class DropboxDownloadTask extends AsyncTask<String, Void, File> {

    public interface OnDropboxDownloadListener {
        void onSuccess(File dropboxFile);
    }

    private static final String APP_KEY = "my-app-key";
    private static final String APP_ACCESS = "my-access-key";
    private static final String TOKEN = "my-token";

    // TODO: See below
    // private final String appKey, appAccess, dropboxToken;

    private final Context context;
    private final AndroidAuthSession session;
    private final DropboxAPI<AndroidAuthSession> dropboxAPI;

    private OnDropboxDownloadListener listener;

    public DropboxDownloadTask(Context c) {
        this.context = c;

        // TODO: Move those strings to a string resource file
        /*
        appKey = c.getResources().getString(R.string.dropbox_app_key);
        appAccess = c.getResources().getString(R.string.dropbox_access_key);
        dropboxToken = c.getResources().getString(R.string.dropbox_token);
        */

        session = buildSession();
        dropboxAPI = new DropboxAPI<AndroidAuthSession>(session);
    }

    public void setOnDownloadListener(OnDropboxDownloadListener listener) {
        this.listener = listener;
    }

    private AndroidAuthSession buildSession() {
        AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_ACCESS);
        AndroidAuthSession session = new AndroidAuthSession(appKeyPair);
        session.setOAuth2AccessToken(TOKEN);
        return session;
    }

    @Override
    protected File doInBackground(String... params) {
        File file;
        if (params.length != 2) {
            throw new IllegalArgumentException("Must give Dropbox to and from paths!");
        }
        String downloadPathTo = params[0];
        String downloadPathFrom = params[1];

        file = new File(downloadPathTo + downloadPathFrom.substring(downloadPathFrom.lastIndexOf('.')));
        if (file.exists()) file.delete();

        try {
            FileOutputStream outputStream = new FileOutputStream(file);
            dropboxAPI.getFile(downloadPathFrom, null, outputStream, null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return file;
    }

    @Override
    protected void onPostExecute(File result) {
        if (this.listener != null) {
            this.listener.onSuccess(result);
        }
    }
}

Now that you have that, you can use from anyplace that you have a Context reference and can implement a OnDropboxDownloadListener. It wasn't clear in your question why you extended an Activity class, but if you were going to use an Activity, it could look like this.

public class MainActivity extends Activity implements DropboxDownloadTask.OnDropboxDownloadListener {

    private DropboxDownloadTask dropboxDownloadTask;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // pass the context 
        dropboxDownloadTask = new DropboxDownloadTask(this);
        // pass the listener 
        dropboxDownloadTask.setOnDownloadListener(this);

        // TODO: Implement 
        downloadFromDropbox("to", "from");

    }

    private void downloadFromDropbox(String downloadPathTo, final String downloadPathFrom) {
        Toast.makeText(getApplicationContext(), "Downloading  Please wait ...", Toast.LENGTH_LONG).show();
        dropboxDownloadTask.execute(downloadPathFrom, downloadPathTo);
    }

    @Override
    public void onSuccess(File dropboxFile) {
        Toast.makeText(getApplicationContext(), "File successfully downloaded.", Toast.LENGTH_SHORT).show();

        Intent promptInstall = new Intent(Intent.ACTION_VIEW)
                .setDataAndType(Uri.fromFile(dropboxFile), "application/vnd.android.package-archive");
        promptInstall.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        startActivity(promptInstall);
    }
}
Comments