package com.letv.commonjar.download;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.letv.commonjar.CLog;
import com.letv.commonjar.download.JDownloadDBHelper.JDownloadTaskColumn;
import com.letv.commonjar.download.JDownloadDBHelper.JDownloadTaskColumnIndex;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Pair;
public class JDownloadManager {
public static final String TAG = CLog.makeTag(JDownloadManager.class);
public static class Request {
private Uri mUri;
private Uri mDataUri;
private List<Pair<String, String>> mRequestHeaders = new ArrayList<Pair<String, String>>();
private CharSequence mTitle;
private CharSequence mDescription;
/**
* This download is visible and shows in the notifications while in
* progress and after completion.
*/
public static final int VISIBILITY_VISIBLE_NOTIFY_COMPLETED = 1;
public static final int VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION = 2;
public Request(String uriString) {
if (uriString == null || "".equals(uriString)) {
throw new NullPointerException();
}
mUri = Uri.parse(uriString);
}
public Request(Uri uri) {
if (uri == null) {
throw new NullPointerException();
}
String scheme = uri.getScheme();
if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) {
throw new IllegalArgumentException("Can only download HTTP/HTTPS URIs: " + uri);
}
mUri = uri;
}
/**
* Add an HTTP header to be included with the download request. The
* header will be added to the end of the list.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html
*
* @param header
* HTTP header name
* @param value
* header value
* @return this object
*/
public Request addRequestHeader(String header, String value) {
if (header == null) {
throw new NullPointerException("header cannot be null");
}
if (header.contains(":")) {
throw new IllegalArgumentException("header may not contain ':'");
}
if (value == null) {
value = "";
}
mRequestHeaders.add(Pair.create(header, value));
return this;
}
private void putIfNonNull(ContentValues contentValues, String key, Object value) {
if (value != null) {
contentValues.put(key, value.toString());
}
}
public Request setDescription(CharSequence description) {
mDescription = description;
return this;
}
private void setDestinationFromBase(File base, String subPath) {
if (subPath == null) {
throw new NullPointerException("subPath cannot be null");
}
mDataUri = Uri.withAppendedPath(Uri.fromFile(base), subPath);
}
/**
* Set the local destination for the downloaded file to a path within
* the application's external files directory
*
* @param context
* @param dirType
* @param subPath
* @return
*/
public Request setDestinationInExternalFilesDir(Context context, String dirType, String subPath) {
setDestinationFromBase(context.getExternalFilesDir(dirType), subPath);
return this;
}
/**
* Set the local destination for the downloaded file to a path within
* the public external storage directory
*
* @param dirType
* @param subPath
* @return
*/
public Request setDestinationInExternalPublicDir(String dirType, String subPath) {
File file = Environment.getExternalStoragePublicDirectory(dirType);
if (file.exists()) {
if (!file.isDirectory()) {
throw new IllegalStateException(file.getAbsolutePath() + " already exists and is not a directory");
}
} else {
if (!file.mkdir()) {
throw new IllegalStateException("Unable to create directory: " + file.getAbsolutePath());
}
}
setDestinationFromBase(file, subPath);
return this;
}
/**
* Set the local destination for the downloaded file. Must be a file URI
* to a path on external storage, and the calling application must have
* the WRITE_EXTERNAL_STORAGE permission
*
* @param uri
* @return
*/
public Request setDestinationUri(Uri uri) {
mDataUri = uri;
return this;
}
public Request setTitle(CharSequence title) {
mTitle = title;
return this;
}
/**
* @param packageName
* @return ContentValues to be passed to DownloadProvider.insert()
* @throws Exception
*/
ContentValues toContentValues(String className) throws Exception {
ContentValues values = new ContentValues();
assert mUri != null;
values.put(JDownloadTaskColumn.URI, mUri.toString());
if (className != null) {
values.put(JDownloadTaskColumn.NOTIFICATION_CLASS, className);
}
if (mDataUri != null) {
values.put(JDownloadTaskColumn.DATA, mDataUri.toString());
} else {
throw new Exception("mDataUri is null");
}
putIfNonNull(values, JDownloadTaskColumn.TITLE, mTitle);
putIfNonNull(values, JDownloadTaskColumn.DESCRIPTION, mDescription);
/**
* //TODO undo list : mRequestHeaders notify mode
*/
CLog.d(TAG, values.toString());
values.put(JDownloadTaskColumn.STATUS, STATUS_QUEUEING);
return values;
}
@Override
public String toString() {
return super.toString();
}
}
public static final String ACTION_DOWNLOAD_TASK_ADD = "com.josyee.download.action_download_add";
public static final String ACTION_DOWNLOAD_TASK_REMOVE = "com.josyee.download.action_download_remove";
public static final String ACTION_DOWNLOAD_PROGRESS = "com.josyee.download.action_download_progress";
public static final String ACTION_DOWNLOAD_COMPLETED = "com.josyee.download.action_download_completed";
public static final String COLUMN_DOWNLOAD_ID = "_download_id";
public final static String COLUMN_PROGRESS = "_download_progress";
public final static String COLUMN_DESCRIPTION = "_download_description";
public final static String COLUMN_STATUS = "_download_status";
public final static int STATUS_QUEUEING = 0;
public final static int STATUS_RUNNING = 1;
public final static int STATUS_PAUSED = 2;
public final static int STATUS_SUCCESSFUL = 3;
public final static int STATUS_FAILED = 4;
public final static int ERROR_UNKNOWN = 1000;
private Context mCtx;
private JDownloadDBUtils mDbUtils;
private LocalBroadcastManager mLocalBroadcastManager;
public JDownloadManager(Context ctx) {
mCtx = ctx;
mDbUtils = new JDownloadDBUtils(ctx);
mLocalBroadcastManager = LocalBroadcastManager.getInstance(ctx);
checkService();
}
public long addQueue(Request request) {
long ret = -1;
try {
ContentValues values = request.toContentValues(null);
ret = mDbUtils.insert(values);
if (ret != -1) {
notifyServiceAdd(ret);
} else {
throw new Exception("insert task failed");
}
} catch (Exception e) {
e.printStackTrace();
}
return ret;
}
public void remove(long id) {
// delete database row in service
notifyServiceRemove(id);
}
public void remove(long... ids) {
// delete database row in service
if (ids == null || ids.length == 0) {
}
notifyServiceRemove(ids[0]);
}
public Cursor queryTask(long id) {
if (id == -1) {
return null;
}
return mDbUtils.query(id);
}
public boolean isInExecute(long id) {
boolean ret = false;
Cursor cursor = queryTask(id);
if (cursor != null && cursor.moveToFirst()) {
int status = cursor.getInt(JDownloadTaskColumnIndex.STATUS);
CLog.d(TAG, "isInExecute status=" + status);
if (status != JDownloadManager.STATUS_SUCCESSFUL && status != JDownloadManager.STATUS_FAILED) {
ret = true;
}
cursor.close();
}
return ret;
}
private void notifyServiceAdd(long id) {
Intent intent = new Intent(ACTION_DOWNLOAD_TASK_ADD);
intent.putExtra(COLUMN_DOWNLOAD_ID, id);
mLocalBroadcastManager.sendBroadcast(intent);
}
private void notifyServiceRemove(long id) {
Intent intent = new Intent(ACTION_DOWNLOAD_TASK_REMOVE);
intent.putExtra(COLUMN_DOWNLOAD_ID, id);
mLocalBroadcastManager.sendBroadcast(intent);
}
private void checkService() {
boolean ret = false;
int pid = android.os.Process.myPid();
ActivityManager manager = (ActivityManager) mCtx.getSystemService(Context.ACTIVITY_SERVICE);
ArrayList<RunningServiceInfo> runnings = (ArrayList<RunningServiceInfo>) manager
.getRunningServices(Integer.MAX_VALUE);
if (runnings != null) {
for (RunningServiceInfo info : runnings) {
//JLog.d(TAG, pid + " name "+info.service.getClassName() + " from "+info.pid +" "+JDownloadService.class.getSimpleName());
if (info.pid==pid && info.service.getClassName().toString().equals(JDownloadService.class.getSimpleName())) {
ret = true;
break;
}
}
}
if (!ret) {
mCtx.startService(new Intent(mCtx, JDownloadService.class));
}
}
}