package com.mcxiaoke.minicat.service;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.util.Log;
import android.webkit.MimeTypeMap;
import android.widget.RemoteViews;
import com.mcxiaoke.minicat.AppContext;
import com.mcxiaoke.minicat.R;
import com.mcxiaoke.minicat.app.UIVersionUpdate;
import com.mcxiaoke.minicat.util.DateTimeHelper;
import com.mcxiaoke.minicat.util.IOHelper;
import com.mcxiaoke.minicat.util.StringHelper;
import com.mcxiaoke.minicat.util.Utils;
import org.oauthsimple.http.Request;
import org.oauthsimple.http.Response;
import org.oauthsimple.http.Verb;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
/**
* @author mcxiaoke
* @version 3.1 2012.02.24
*/
public class DownloadService extends BaseIntentService {
public static final String UPDATE_VERSION_FILE = "http://apps.fanfou.com/android/update.json";
public static final int TYPE_CHECK = 0;
public static final int TYPE_DOWNLOAD = 1;
private static final String TAG = DownloadService.class.getSimpleName();
private static final int NOTIFICATION_PROGRESS_ID = -12345;
private static final int MSG_PROGRESS = 0;
private static final int MSG_SUCCESS = 1;
private NotificationManager nm;
private Notification notification;
private Handler mHandler;
public DownloadService() {
super("DownloadService");
}
public static void set(Context context, boolean set) {
if (set) {
set(context);
} else {
unset(context);
}
}
public static void set(Context context) {
Calendar c = Calendar.getInstance();
c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH),
c.get(Calendar.DAY_OF_MONTH), 11, 0);
c.add(Calendar.DATE, 1);
long interval = 5 * 24 * 3600 * 1000;
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
am.setInexactRepeating(AlarmManager.RTC, c.getTimeInMillis(), interval,
getPendingIntent(context));
if (AppContext.DEBUG) {
Log.d(TAG,
"set interval=2day first time="
+ DateTimeHelper.formatDate(c.getTime()));
}
}
public static void unset(Context context) {
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
am.cancel(getPendingIntent(context));
if (AppContext.DEBUG) {
Log.d(TAG, "unset");
}
}
private final static PendingIntent getPendingIntent(Context context) {
Intent intent = new Intent(context, DownloadService.class);
intent.putExtra("type", TYPE_CHECK);
PendingIntent pi = PendingIntent.getService(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
return pi;
}
public static void startDownload(Context context, String url) {
Intent intent = new Intent(context, DownloadService.class);
intent.putExtra("type", TYPE_DOWNLOAD);
intent.putExtra("url", url);
context.startService(intent);
}
public static VersionInfo fetchVersionInfo() {
try {
Request request = new Request(Verb.GET, UPDATE_VERSION_FILE);
Response response = request.send();
int statusCode = response.getCode();
if (AppContext.DEBUG) {
Log.d(TAG, "statusCode=" + statusCode);
}
if (statusCode == 200) {
String content = response.getBody();
if (AppContext.DEBUG) {
Log.d(TAG, "response=" + content);
}
return VersionInfo.parse(content);
}
} catch (Exception e) {
if (AppContext.DEBUG) {
e.printStackTrace();
}
}
return null;
}
public static void notifyUpdate(VersionInfo info, Context context) {
String versionInfo = info.versionName;
NotificationManager nm = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
final NotificationCompat.Builder builder = new Builder(context);
builder.setSmallIcon(R.drawable.ic_stat_app);
builder.setWhen(System.currentTimeMillis());
builder.setContentIntent(PendingIntent.getActivity(context, 0,
getNewVersionIntent(context, info), 0));
builder.setTicker("饭否客户端有新版本:" + versionInfo);
builder.setContentText("饭否客户端有新版本:" + versionInfo);
builder.setSubText("点击查看更新内容");
builder.setAutoCancel(true);
nm.notify(2, builder.build());
}
public static void showUpdateConfirmDialog(final Context context,
final VersionInfo info) {
DialogInterface.OnClickListener li = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startDownload(context, info.downloadUrl);
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("发现新版本,是否升级?").setCancelable(true)
.setNegativeButton("以后再说", null);
builder.setPositiveButton("立即升级", li);
StringBuffer sb = new StringBuffer();
sb.append("安装版本:").append(AppContext.versionName).append("(Build")
.append(AppContext.versionCode).append(")");
sb.append("\n最新版本:").append(info.versionName).append("(Build")
.append(info.versionCode).append(")");
sb.append("\n更新日期:").append(info.releaseDate);
sb.append("\n更新级别:").append(info.forceUpdate ? "重要升级" : "一般升级");
sb.append("\n更新内容:\n").append(info.changelog);
builder.setMessage(sb.toString());
AlertDialog dialog = builder.create();
dialog.show();
}
public static Intent getNewVersionIntent(Context context,
final VersionInfo info) {
Intent intent = new Intent(context, UIVersionUpdate.class);
intent.putExtra("data", info);
return intent;
}
private void log(String message) {
Log.d("DownloadService", message);
}
@Override
public void onCreate() {
super.onCreate();
mHandler = new DownloadHandler();
}
@Override
protected void onHandleIntent(Intent intent) {
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int type = intent.getIntExtra("type", TYPE_CHECK);
if (type == TYPE_CHECK) {
check();
} else if (type == TYPE_DOWNLOAD) {
String url = intent.getStringExtra("url");
log("onHandleIntent TYPE_DOWNLOAD url=" + url);
if (!StringHelper.isEmpty(url)) {
download(url);
}
}
}
private void check() {
VersionInfo info = fetchVersionInfo();
if (AppContext.DEBUG) {
if (info != null) {
notifyUpdate(info, this);
return;
}
}
// for debug
if (info != null && info.versionCode > AppContext.versionCode) {
notifyUpdate(info, this);
}
}
private void download(String url) {
showProgress();
InputStream is = null;
BufferedOutputStream bos = null;
final long UPDATE_TIME = 2000;
long lastTime = 0;
try {
Request request = new Request(Verb.GET, url);
Response response = request.send();
int statusCode = response.getCode();
if (statusCode == 200) {
long total = response.getContentLength();
long download = 0;
is = response.getInputStream();
File file = new File(IOHelper.getDownloadDir(this), "fanfou_"
+ DateTimeHelper.formatDateFileName(new Date())
+ ".apk");
bos = new BufferedOutputStream(new FileOutputStream(file));
byte[] buffer = new byte[8196];
int read = -1;
while ((read = is.read(buffer)) != -1) {
bos.write(buffer, 0, read);
download += read;
int progress = (int) (100.0 * download / total);
if (AppContext.DEBUG) {
log("progress=" + progress);
}
if (System.currentTimeMillis() - lastTime >= UPDATE_TIME) {
Message message = mHandler.obtainMessage(MSG_PROGRESS);
message.arg1 = progress;
mHandler.sendMessage(message);
lastTime = System.currentTimeMillis();
}
;
}
bos.flush();
if (download >= total) {
Message message = new Message();
message.what = MSG_SUCCESS;
message.getData().putString("filename",
file.getAbsolutePath());
mHandler.sendMessage(message);
}
}
} catch (IOException e) {
if (AppContext.DEBUG) {
Log.e(TAG, "download error: " + e.getMessage());
e.printStackTrace();
}
} finally {
nm.cancel(NOTIFICATION_PROGRESS_ID);
IOHelper.forceClose(is);
IOHelper.forceClose(bos);
}
}
private void showProgress() {
notification = new Notification(R.drawable.ic_notify_download,
"正在下载饭否客户端", System.currentTimeMillis());
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.contentIntent = PendingIntent.getActivity(this, 0,
new Intent(), 0);
RemoteViews view = new RemoteViews(getPackageName(),
R.layout.download_notification);
view.setTextViewText(R.id.download_notification_text, "正在下载饭否客户端 0%");
view.setProgressBar(R.id.download_notification_progress, 100, 0, false);
notification.contentView = view;
nm.notify(NOTIFICATION_PROGRESS_ID, notification);
}
private void updateProgress(final int progress) {
RemoteViews view = new RemoteViews(getPackageName(),
R.layout.download_notification);
view.setTextViewText(R.id.download_notification_text, "正在下载饭否客户端 "
+ progress + "%");
view.setInt(R.id.download_notification_progress, "setProgress",
progress);
notification.contentView = view;
nm.notify(NOTIFICATION_PROGRESS_ID, notification);
}
@SuppressWarnings("unused")
private PendingIntent getInstallPendingIntent(String fileName) {
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
Utils.getExtension(fileName));
if (mimeType != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(fileName)), mimeType);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
return pi;
}
return null;
}
private class DownloadHandler extends Handler {
@Override
public void handleMessage(Message msg) {
if (AppContext.DEBUG) {
log("DownloadHandler what=" + msg.what + " progress="
+ msg.arg1);
}
if (MSG_PROGRESS == msg.what) {
int progress = msg.arg1;
updateProgress(progress);
} else if (MSG_SUCCESS == msg.what) {
nm.cancel(NOTIFICATION_PROGRESS_ID);
String filePath = msg.getData().getString("filename");
Utils.open(DownloadService.this, filePath);
}
}
}
}