package com.bigdo.service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import com.bigdo.app.R;
import com.bigdo.common.BDSQLiteHelper;
import com.bigdo.common.RConfig;
import com.bigdo.common.VideoDownHelper;
import com.bigdo.util.MD5;
import com.bigdo.util.Pub;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.widget.RelativeLayout;
import android.widget.RemoteViews;
import android.widget.TextView;
public class DownloadService extends Service {
NotificationManager notification_m;
Notification notification;
DownloadVideo download;
private final IBinder result = new LocalBinder();
DownBroadcastReceiver downBroadcast = null;
public static final String ACTION = "com.bigdo.service.DownloadService";
public class LocalBinder extends Binder {
public DownloadService getService() {
return DownloadService.this;
}
}
@Override
public IBinder onBind(Intent arg0) {
return result;
}
@Override
public void onCreate() {
super.onCreate();
this.setForeground(true);
startDown();
startDownBroadcast();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
startDown();
startDownBroadcast();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startDown();
startDownBroadcast();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
stopDown();
stopVideoBroadcast();
}
private void startDownBroadcast() {
if (downBroadcast == null) {
downBroadcast = new DownBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(DownloadService.ACTION);
registerReceiver(downBroadcast, filter);
Log.e("downBroadcast", "start");
}
}
private void stopVideoBroadcast() {
if (downBroadcast != null) {
try {
unregisterReceiver(downBroadcast);
} catch (Exception e) {
}
downBroadcast = null;
Log.e("downBroadcast", "stop");
}
}
public class DownBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
String action = arg1.getAction();
if (action.equals(DownloadService.ACTION)) {
if (download != null) {
download.unLock();
}
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
if (isConnected()) {
if (download != null) {
download.unLock();
}
}
}
}
}
public boolean isConnected() {
ConnectivityManager mConnectivityManager = (ConnectivityManager) this
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWiFiNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (mWiFiNetworkInfo != null) {
if (!mWiFiNetworkInfo.isAvailable()) {
NetworkInfo mMobileNetworkInfo = mConnectivityManager
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (mWiFiNetworkInfo != null) {
return mMobileNetworkInfo.isAvailable()
&& mMobileNetworkInfo.isConnected();
}
} else {
return true;
}
}
return false;
}
private void stopDown() {
if (download != null) {
download.interrupt();
}
download = null;
}
private void startDown() {
if (download == null) {
download = new DownloadVideo();
download.start();
} else {
download.unLock();
}
}
private class DownloadVideo extends Thread {
private Object lockObj = new Object();
private String baseDir = "", baseUrl = "";
@Override
public void run() {
super.run();
download();
}
public void unLock() {
try {
synchronized (lockObj) {
lockObj.notifyAll();
}
} catch (Exception e1) {
}
}
public void lock() {
try {
synchronized (lockObj) {
lockObj.wait(1000 * 60);
}
} catch (Exception e1) {
}
}
private void download() {
BDSQLiteHelper sqlobj = null;
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
baseDir = Environment.getExternalStorageDirectory()
+ RConfig.Video_Dir;
baseUrl = RConfig.getBaseUrl(DownloadService.this);
DownInfo pre_down = null;
while (!this.isInterrupted()) {
if (isConnected()) {
DownInfo down = look();
if (down != null) {
if (pre_down != null
&& pre_down.idtype == down.idtype
&& pre_down.idvideo == down.idvideo) {
pre_down = null;
lock();
}
doDown(down);
pre_down = down;
continue;
}
pre_down = null;
}
lock();
pre_down = null;
}
}
}
private void doDown(DownInfo down) {
BDSQLiteHelper sqlobj = null;
String _f = VideoDownHelper.cacheFileName(down.idtype,
down.idvideo, down.downurl);
String l_f = _f + ".r.t";
String l_f_f = _f + ".r";
int lv = 0;
try {
startDown(down.idvideo, down.title);
File dir = new File(baseDir);
if (!dir.exists()) {
dir.mkdirs();
}
File dff = new File(dir, l_f_f);
if (dff.exists()) {
updateDown(down);
downFinish(down.idvideo);
return;
}
File df = new File(dir, l_f);
long slg = 0, tc = 0;
if (df.exists()) {
slg = df.length() - 180;
}
if (slg < 0) {
slg = 0;
}
String url = "";
String downurl = down.downurl;
int hi = downurl.indexOf("http://");
if (hi >= 0) {
url = downurl;
} else {
hi = downurl.indexOf("/");
if (hi == 0) {
hi++;
downurl = downurl.substring(hi);
}
downurl = baseUrl + downurl;
}
url = Pub.handleDownVideoUrl(downurl);
try {
Log.e("doDown", url);
} catch (Exception e) {
}
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
if (slg > 0) {
try {
HttpClient client_test = new DefaultHttpClient();
HttpGet request_test = new HttpGet(url);
HttpResponse response_test = client_test
.execute(request_test);
int code = response_test.getStatusLine()
.getStatusCode();
if (code == 200) {
tc = response_test.getEntity().getContentLength();
}
request_test.abort();
} catch (Exception e) {
}
if (tc > 0 && slg >= tc) {
copyFile(l_f, l_f_f);
updateDown(down);
downFinish(down.idvideo);
return;
}
}
// 设置下载的数据位置XX字节到结尾
Header header_size = new BasicHeader("Range", "bytes=" + slg
+ "-");
request.addHeader(header_size);
HttpResponse response = client.execute(request);
int code = response.getStatusLine().getStatusCode();
long fc = 0;
if (code == 200 || code == 206) {
InputStream in = null;
FileOutputStream out = null;
try {
HttpEntity respEnt = response.getEntity();
if (respEnt.isStreaming()) {
if (tc <= 0) {
tc = respEnt.getContentLength();
}
in = respEnt.getContent();
if (slg > 0) {
// in.skip(slg);
out = new FileOutputStream(df, true);
} else {
out = new FileOutputStream(df);
}
byte[] buf = new byte[2 * 1024];
fc = slg;
if (fc > 0) {
lv = (int) ((fc / tc) * 100);
if (fc >= tc) {
lv = 100;
copyFile(l_f, l_f_f);
updateDown(down);
downFinish(down.idvideo);
return;
}
downing(down.idvideo, lv);
}
int lg = 0, flv = 0, sumlv = 0;
long lt = 0;
boolean frist = true;
try {
while ((lg = in.read(buf)) > 0) {
if (slg <= 0 && frist) {
byte[] pre_data = "123456789987654321123456789987654321"
.getBytes();
for (int j = 0; j < 5; j++) {
out.write(pre_data);
}
out.flush();
frist = false;
}
out.write(buf, 0, lg);
out.flush();
fc += lg;
lv = (int) ((fc * 1.0000 / tc) * 100);
if (lv > 100) {
lv = 100;
}
sumlv = Math.abs(flv - lv);
if (Math.abs((lt - System
.currentTimeMillis())) >= 400
|| sumlv >= 3 || lv >= 100) {
downing(down.idvideo, lv);
flv = lv;
lt = System.currentTimeMillis();
}
}
} catch (Exception e) {
downError(down.idvideo, "视频下载中断,已完成 " + lv
+ "%");
}
if (fc >= tc) {
copyFile(l_f, l_f_f);
downFinish(down.idvideo);
updateDown(down);
}
buf = null;
}
} catch (Exception ex) {
downError(down.idvideo, "视频下载出错,已完成 " + lv + "%");
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception e) {
}
out = null;
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
}
in = null;
}
} else if (code >= 400 && code < 500) {
downError(down.idvideo, "视频不存在 或 连接失效.");
delDown(down);
downFile404(l_f, l_f_f);
} else {
downError(down.idvideo, "视频下载失败,已完成 " + lv + "%");
// delDown(down);
}
} catch (Exception ex) {
downError(down.idvideo, "视频下载出错,已完成 " + lv + "%");
// delDown(down);
// downFile404(l_f, l_f_f);
}
}
private void downFile404(String t, String f) {
try {
File tf = new File(baseDir, t);
File tff = new File(baseDir, f);
tf.delete();
tff.delete();
} catch (Exception e) {
}
}
private void copyFile(String t, String f) {
File tf = new File(baseDir, t);
File tff = new File(baseDir, f);
if (!tf.renameTo(tff)) {
try {
if (tf.exists()) {
FileInputStream in = new FileInputStream(tf);
FileOutputStream out = new FileOutputStream(tff);
byte[] buf = new byte[4 * 1024];
while ((in.read(buf)) > 0) {
out.write(buf);
out.flush();
}
buf = null;
out.close();
in.close();
tf.delete();
}
} catch (Exception e) {
}
}
try {
tf.delete();
} catch (Exception e) {
}
}
}
private DownInfo look() {
BDSQLiteHelper sqlobj = null;
DownInfo down = null;
SQLiteDatabase sqlobj_r = null;
Cursor cu = null;
try {
sqlobj = new BDSQLiteHelper(DownloadService.this);
sqlobj_r = sqlobj.getReadableDatabase();
String sql = "select * from download where idtype > 0 and idvideo > 0 and isfinish = 0 order by idown asc limit 0,1";
cu = sqlobj_r.rawQuery(sql, null);
while (cu.moveToNext()) {
int idown = cu.getInt(cu.getColumnIndex("idown"));
int idvideo = cu.getInt(cu.getColumnIndex("idvideo"));
int idtype = cu.getInt(cu.getColumnIndex("idtype"));
String title = cu.getString(cu.getColumnIndex("title"));
String downurl = cu.getString(cu.getColumnIndex("downurl"));
if (title != null && !title.equals("") && downurl != null
&& !downurl.equals("")) {
down = new DownInfo();
down.idown = idown;
down.idvideo = idvideo;
down.idtype = idtype;
down.title = title;
down.downurl = downurl;
}
break;
}
} catch (Exception e) {
Log.e("look", e.getMessage());
}
try {
if (cu != null) {
cu.close();
cu = null;
}
} catch (Exception ex) {
}
try {
if (sqlobj_r != null) {
sqlobj_r.close();
sqlobj_r = null;
}
} catch (Exception ex) {
}
try {
if (sqlobj != null) {
sqlobj.close();
sqlobj = null;
}
} catch (Exception ex) {
}
return down;
}
private void delDown(DownInfo down) {
BDSQLiteHelper sqlobj = null;
SQLiteDatabase sqlobj_w = null;
try {
sqlobj = new BDSQLiteHelper(DownloadService.this);
sqlobj_w = sqlobj.getWritableDatabase();
sqlobj_w.delete("download", "idtype = ? and idvideo = ?",
new String[] { down.idtype + "", down.idvideo + "" });
} catch (Exception e) {
}
try {
if (sqlobj_w != null) {
sqlobj_w.close();
sqlobj_w = null;
}
} catch (Exception ex) {
}
try {
if (sqlobj != null) {
sqlobj.close();
sqlobj = null;
}
} catch (Exception ex) {
}
}
private void updateDown(DownInfo down) {
BDSQLiteHelper sqlobj = null;
SQLiteDatabase sqlobj_w = null;
try {
sqlobj = new BDSQLiteHelper(DownloadService.this);
sqlobj_w = sqlobj.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("isfinish", 1);
sqlobj_w.update("download", cv, "idtype = ? and idvideo = ? ",
new String[] { down.idtype + "", down.idvideo + "" });
} catch (Exception e) {
}
try {
if (sqlobj_w != null) {
sqlobj_w.close();
sqlobj_w = null;
}
} catch (Exception ex) {
}
try {
if (sqlobj != null) {
sqlobj.close();
sqlobj = null;
}
} catch (Exception ex) {
}
}
private void initNotification(int idNotify) {
if (notification_m == null) {
notification_m = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
notification = new Notification(R.drawable.ra_downing, "下载",
System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL;// //Notification.FLAG_ONGOING_EVENT
// | Notification.FLAG_AUTO_CANCEL;
// host.setTextViewText(R.id.ra_downloadfile_filename, fileName
// + lastSuffix);
notification.contentView = new RemoteViews(getPackageName(),
R.layout.activity_downloadfile);
Intent i = new Intent();
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
notification.contentIntent = pi;
// notification.setLatestEventInfo(context, "", "", contentIntent);
if (idNotify > Integer.MAX_VALUE) {
idNotify = 1200;
}
notification_m.notify(idNotify, notification);
}
private void startDown(int idNotify, String title) {
initNotification(idNotify);
notification.icon = R.drawable.ra_downing;
notification.contentView.setViewVisibility(R.id.ra_downloadfile_finish,
TextView.GONE);
notification.contentView.setViewVisibility(
R.id.ra_downloadfile_progress, RelativeLayout.VISIBLE);
notification.contentView.setTextViewText(R.id.ra_downloadfile_filename,
title);
notification.contentView.setImageViewResource(
R.id.ra_downloadfile_fileimg, notification.icon);
notification_m.notify(idNotify, notification);
}
private void downFinish(int idNotify) {
notification.icon = R.drawable.ra_downfinish;
notification.contentView.setViewVisibility(
R.id.ra_downloadfile_progress, RelativeLayout.GONE);
notification.contentView.setViewVisibility(R.id.ra_downloadfile_finish,
TextView.VISIBLE);
notification.contentView.setTextViewText(R.id.ra_downloadfile_finish,
"下载完成!");
notification.contentView.setImageViewResource(
R.id.ra_downloadfile_fileimg, notification.icon);
notification_m.notify(idNotify, notification);
}
private void downing(int idNotify, int lv) {
notification.icon = R.drawable.ra_downing;
notification.contentView.setViewVisibility(R.id.ra_downloadfile_finish,
TextView.GONE);
notification.contentView.setViewVisibility(
R.id.ra_downloadfile_progress, RelativeLayout.VISIBLE);
notification.contentView.setProgressBar(
R.id.ra_downloadfile_progressbar, 100, lv, false);
notification.contentView.setTextViewText(
R.id.ra_downloadfile_progressnum, lv + "%");
notification.contentView.setImageViewResource(
R.id.ra_downloadfile_fileimg, notification.icon);
notification_m.notify(idNotify, notification);
}
private void downError(int idNotify, String error) {
notification.icon = R.drawable.ra_downerror;
notification.contentView.setViewVisibility(
R.id.ra_downloadfile_progress, RelativeLayout.GONE);
notification.contentView.setViewVisibility(R.id.ra_downloadfile_finish,
TextView.VISIBLE);
notification.contentView.setTextViewText(R.id.ra_downloadfile_finish,
error);
notification.contentView.setImageViewResource(
R.id.ra_downloadfile_fileimg, notification.icon);
notification_m.notify(idNotify, notification);
}
}