package org.carelife.creader.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Calendar;
import java.util.Observable;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.carelife.creader.util.FileUtil;
import org.carelife.creader.R;
import org.carelife.creader.ui.activity.MainActivity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
public class UpdateService extends Service {
public static final int DOWNLOAD_ING = 0;
public static final int DOWNLOAD_PAUSE = 1;
public static final int DOWNLOAD_COMPLETE = 2;
public static final int DOWNLOAD_FAIL = 3;
public static final int DOWNLOAD_SPACE_NOT_ENOUGH = 4;
private static final String SPACE_NOT_ENOUGH = "space_not_enough";
public static final String FILE_KEY = "fileName";
public static final String URL_KEY = "updateUrl";
public static final String ACN_KEY = "activityClassName";
public static final String CONTROL_KEY = "control";
public static final int CONTROL_DEFAULT_VALUE = 0;
private Thread downloadThread;
private int control;
private boolean N_FLAG = true;
/* (non-Javadoc)
* @see android.app.Service#onBind(android.content.Intent)
*/
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
//�ļ��洢
private FileOutputStream updateFileOs = null;
private String fileAbsolutePath = null;
//֪ͨ��
private NotificationManager updateNotificationManager = null;
private Notification updateNotification = null;
//֪ͨ����תIntent
private Intent updateIntent = null;
private PendingIntent updatePendingIntent = null;
private String mFileName = null;
class SavedFile{
public SavedFile(String fileName, Context mContext) throws IOException{
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String dir = Environment.getExternalStorageDirectory().getAbsoluteFile() + "/sogounovel/download/Version/";
clearDownloadApk(dir);
fileAbsolutePath = dir + fileName;
File tmp = new File(dir);
if(!tmp.exists()){
tmp.mkdirs();
}
}else{
fileAbsolutePath = getFilesDir().getAbsolutePath() + "/";
clearDownloadApk(fileAbsolutePath);
}
}
public void clearDownloadApk(String dir){
Log.i("clearDownloadApk", dir);
File downloadDirFile = new File(dir);
if(downloadDirFile.isDirectory()){
File[] files = downloadDirFile.listFiles();
if(files != null){
for(int i = 0; i < files.length; i++){
File file = files[i];
String filename = file.getName().toLowerCase();
if(filename.startsWith("sogounovel") && filename.endsWith("apk")){
Log.i("file delete", filename);
if(!filename.equals(mFileName.toLowerCase())){//��ɾ��ͬ�汾�ļ�
file.delete();
}
}
}
}
}
}
}
private String url;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//�����ļ�
try{
url = intent.getStringExtra(URL_KEY);
control = intent.getIntExtra("control", CONTROL_DEFAULT_VALUE);
this.updateNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
this.updateNotification = new Notification();
this.updateNotification.icon = R.drawable.ic_launcher;
//�������ع����У����֪ͨ�����ص�������
updateIntent = new Intent(this, MainActivity.class);
//updateIntent = new Intent();
//updateIntent = new Intent(Intent.ACTION_MAIN);
//updateIntent.addCategory(Intent.CATEGORY_LAUNCHER);
//updateIntent.setComponent(new ComponentName(this.getPackageName(), this.getPackageName() + "." + intent.getStringExtra(ACN_KEY)));
//updateIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
updatePendingIntent = PendingIntent.getActivity(this,0,updateIntent,0);
if(control == CONTROL_DEFAULT_VALUE){
//����֪ͨ����ʾ����
updateNotification.tickerText = "��ʼ����";
updateNotification.flags = Notification.FLAG_AUTO_CANCEL;
updateNotification.setLatestEventInfo(this,"SogouNovel����","0%",updatePendingIntent);
//����֪ͨ
// if(woWenWenYYConfig.getBoolean(Values.OUT_APPLICATION)){
// updateNotificationManager.notify(0,updateNotification);
// }else{
// updateNotificationManager.cancel(0);
// }
updateNotificationManager.notify(0,updateNotification);
}
//����һ���µ��߳����أ����ʹ��Serviceͬ�����أ��ᵼ��ANR���⣬Service����Ҳ������
if(this.downloadThread != null){
Log.i("this.downloadThread is alive", String.valueOf(this.downloadThread.isAlive()));
}
if(this.downloadThread == null || (this.downloadThread != null && !this.downloadThread.isAlive())){
mFileName = intent.getStringExtra(FILE_KEY);
new SavedFile(mFileName , UpdateService.this);
updateRunnable upRunnable = new updateRunnable();
upRunnable.resume();
}else if(this.downloadThread != null && this.downloadThread.isAlive()){
super.onStartCommand(intent, flags, startId);
}
}catch(Exception e){
e.printStackTrace();
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy(){
if(updateFileOs!=null){
try {
updateFileOs.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private Handler updateHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case DOWNLOAD_COMPLETE:
//�����װPendingIntent��
// if(woWenWenYYConfig.iskeyExist(Values.INTRO)){
// woWenWenYYConfig.putBoolean(Values.INTRO, true);
// }
Uri uri = Uri.fromFile(new File(UpdateService.this.fileAbsolutePath));
Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
installIntent.setDataAndType(uri, "application/vnd.android.package-archive");
updatePendingIntent = PendingIntent.getActivity(UpdateService.this, 0, installIntent, 0);
//updateNotification.defaults = Notification.DEFAULT_SOUND;//��������
updateNotification.flags = Notification.FLAG_AUTO_CANCEL;
updateNotification.setLatestEventInfo(UpdateService.this, "SogouNovel����", "������ɣ������װ", updatePendingIntent);
updateNotification.tickerText = "�������";
updateNotificationManager.notify(0, updateNotification);
//updateNotificationManager.cancel(0);
//startActivity(installIntent);
//ֹͣ����
stopService(updateIntent);
break;
case DOWNLOAD_FAIL:
//����ʧ��
if(control == CONTROL_DEFAULT_VALUE){
updateNotification.tickerText = "����ʧ��";
updateNotification.setLatestEventInfo(UpdateService.this, "SogouNovel����", "����ʧ��", updatePendingIntent);
// if(woWenWenYYConfig.getBoolean(Values.OUT_APPLICATION)){
// updateNotificationManager.notify(0, updateNotification);
// }else{
// updateNotificationManager.cancel(0);
// }
updateNotificationManager.notify(0, updateNotification);
stopService(updateIntent);
}
break;
case DOWNLOAD_SPACE_NOT_ENOUGH:
//�ռ䲻��
if(control == CONTROL_DEFAULT_VALUE){
updateNotification.tickerText = "�ռ䲻��";
updateNotification.setLatestEventInfo(UpdateService.this, "SogouNovel����", "�ռ䲻��", updatePendingIntent);
// if(woWenWenYYConfig.getBoolean(Values.OUT_APPLICATION)){
// updateNotificationManager.notify(0, updateNotification);
// }else{
// updateNotificationManager.cancel(0);
// }
updateNotificationManager.notify(0, updateNotification);
stopService(updateIntent);
}
break;
default:
stopService(updateIntent);
break;
}
}
};
public class updateRunnable extends Observable implements Runnable {
Message message = updateHandler.obtainMessage();
int downloadStatus = -1;
long startTime=0;
int downloadCount = 0;
int downLoadPercent = 0;
int currentSize = 0;
int totalSize = 0;
int updateTotalSize = 0;
boolean isPaused = false;
public void stopService(){
UpdateService.this.stopService(updateIntent);
}
public String getFilePath(){
return UpdateService.this.fileAbsolutePath;
}
public int getDownloadStatus() {
return downloadStatus;
}
public void setDownloadStatus(int downloadStatus) {
this.downloadStatus = downloadStatus;
}
public int getDownLoadPercent() {
return downLoadPercent;
}
public void setDownLoadPercent(int downLoadPercent) {
this.downLoadPercent = downLoadPercent;
}
public int getCurrentSize() {
return currentSize;
}
public void setCurrentSize(int currentSize) {
this.currentSize = currentSize;
}
public long getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) {
this.totalSize = totalSize;
}
public int getUpdateTotalSize() {
return updateTotalSize;
}
public void setUpdateTotalSize(int updateTotalSize) {
this.updateTotalSize = updateTotalSize;
}
public void resume() {
downloadStatus = DOWNLOAD_ING;
stateChanged();
download();
}
private void download() {
Thread thread = new Thread(this);
// if(VersionController.getVersionDownloadItem() != null){
// this.addObserver(VersionController.getVersionDownloadItem());
// }
thread.start();
}
public void run() {
message.what = DOWNLOAD_COMPLETE;
try{
//���غ�������QQΪ����
//����Ȩ��<uses-permission android:name="android.permission.INTERNET">;
//long downloadSize = downloadUpdateFile("http://softfile.3g.qq.com:8080/msoft/179/1105/10753/MobileQQ1.0(Android)_Build0198.apk", updateFileOs);
Boolean isDownloadSucc = downloadUpdateFile(url);
if(isDownloadSucc){
//���سɹ�
updateHandler.sendMessage(message);
}
}catch(Exception ex){
ex.printStackTrace();
if(ex.getMessage() != null){
if(ex.getMessage().equals(SPACE_NOT_ENOUGH)){
message.what = DOWNLOAD_SPACE_NOT_ENOUGH;
//�ռ䲻��
updateHandler.sendMessage(message);
}else{
message.what = DOWNLOAD_FAIL;
//����ʧ��
updateHandler.sendMessage(message);
}
}
}
}
// Get this download's speed
public float getSpeed() {
float s= (float) ((totalSize - currentSize)/(1024*1.0));
Calendar cal = Calendar.getInstance();
long elapsed = cal.getTimeInMillis();
elapsed = elapsed-startTime;
Log.i("s", String.valueOf(s));
Log.i("elapsed", String.valueOf(elapsed));
s= (float) (s / (elapsed/(1000*1.0)));
Log.i("speed", s + "k/s");
return s;
}
public Boolean downloadUpdateFile(String downloadUrl) throws Exception {
//���������ش���ܶ࣬�ҾͲ��������˵��
Boolean isDownloadSucc = false;
// HttpURLConnection httpConnection = null;
HttpClient client = null;
InputStream is = null;
try {
//client
BasicHttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 7000);
HttpConnectionParams.setSoTimeout(httpParams, 7000);
httpParams.setParameter("User-Agent", "SogouNovel");
HttpGet httpGet = new HttpGet(downloadUrl);
client = new DefaultHttpClient(httpParams);
HttpResponse response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
HttpEntity entity = response.getEntity();
updateTotalSize += (int) entity.getContentLength();
//connection
// URL url = new URL(downloadUrl);
// httpConnection = (HttpURLConnection)url.openConnection();
//
// httpConnection.setRequestProperty("User-Agent", "SogouNovel");
// if(currentSize > 0) {
// httpConnection.setRequestProperty("RANGE", "bytes=" + currentSize + "-");
// updateTotalSize = currentSize;
// }
// httpConnection.setConnectTimeout(7000);
// httpConnection.setReadTimeout(7000);
// httpConnection.connect();
// System.out.println(httpConnection.getContentLength());
//
// updateTotalSize += httpConnection.getContentLength();
// System.out.println("size is ="+updateTotalSize);
/*Set<String> set = httpConnection.getHeaderFields().keySet();
Iterator<String> iter = set.iterator();
while(iter.hasNext()){
String key = iter.next();
Log.d("what the fuck", key + " !@#!@# " + httpConnection.getHeaderField(key) );
}*/
try{
File file = new File(fileAbsolutePath);
if(file.exists()){
if(file.length() == updateTotalSize){
downloadStatus = DOWNLOAD_COMPLETE;
stateChanged();
isDownloadSucc = true;
Message message = updateHandler.obtainMessage();
message.what = DOWNLOAD_COMPLETE;
updateHandler.sendMessage(message);
return isDownloadSucc;
}else{
if(currentSize == 0){
if(file.length() > 0 && file.length() < updateTotalSize)
file.delete();
}
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
updateFileOs = new FileOutputStream(fileAbsolutePath, true);
}else{
updateFileOs = UpdateService.this.openFileOutput(mFileName, Context.MODE_APPEND);
}
}
}else{
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
updateFileOs = new FileOutputStream(fileAbsolutePath, true);
}else{
updateFileOs = UpdateService.this.openFileOutput(mFileName, Context.MODE_APPEND);
}
}
}catch(Exception e){
e.printStackTrace();
}
if(!FileUtil.isEnoughForDownload(Long.valueOf(updateTotalSize))){
downloadStatus = DOWNLOAD_FAIL;
stateChanged();
throw new Exception(SPACE_NOT_ENOUGH);
}
if (statusCode == 404) {
downloadStatus = DOWNLOAD_FAIL;
stateChanged();
throw new Exception("fail!");
}
if (startTime==0)
startTime=Calendar.getInstance().getTimeInMillis();
// is = httpConnection.getInputStream();
is = entity.getContent();
byte buffer[] = new byte[4096];
int readsize = 0;
while((downloadStatus == DOWNLOAD_ING) && ((readsize = is.read(buffer)) > 0)){
updateFileOs.write(buffer, 0, readsize);
totalSize += readsize;
if(control == CONTROL_DEFAULT_VALUE){
if(N_FLAG && updateTotalSize == -1){
N_FLAG = false;
updateNotification.setLatestEventInfo(UpdateService.this, "��������", "���Ե�", updatePendingIntent);
updateNotificationManager.notify(0, updateNotification);
}
//Ϊ�˷�ֹƵ����֪ͨ����Ӧ�óԽ����ٷֱ�����10��֪ͨһ��
downLoadPercent = (int) (totalSize * 100 / updateTotalSize );
if((downloadCount == 0)||downLoadPercent > (downloadCount - 1)){
downloadCount += 5;
if(downLoadPercent < 100){
downloadStatus = DOWNLOAD_ING;
if(totalSize > currentSize){
stateChanged();
}
if(updateTotalSize != -1){
updateNotification.setLatestEventInfo(UpdateService.this, "��������", String.valueOf(downLoadPercent) + "%", updatePendingIntent);
// if(woWenWenYYConfig.getBoolean(Values.OUT_APPLICATION)){
// updateNotificationManager.notify(0, updateNotification);
// }else{
// updateNotificationManager.cancel(0);
// }
}else{
updateNotification.setLatestEventInfo(UpdateService.this, "��������", "���Ե�", updatePendingIntent);
}
updateNotificationManager.notify(0, updateNotification);
}else{
downloadStatus = DOWNLOAD_COMPLETE;
stateChanged();
isDownloadSucc = true;
//updateNotification.setLatestEventInfo(UpdateService.this, "�������", String.valueOf(downLoadPercent) + "%", updatePendingIntent);
//updateNotificationManager.notify(0, updateNotification);
Message message = updateHandler.obtainMessage();
message.what = DOWNLOAD_COMPLETE;
updateHandler.sendMessage(message);
}
}
}else{
if(totalSize == updateTotalSize){
downloadStatus = DOWNLOAD_COMPLETE;
stateChanged();
isDownloadSucc = true;
//updateNotification.setLatestEventInfo(UpdateService.this, "�������", String.valueOf(downLoadPercent) + "%", updatePendingIntent);
//updateNotificationManager.notify(0, updateNotification);
Message message = updateHandler.obtainMessage();
message.what = DOWNLOAD_COMPLETE;
updateHandler.sendMessage(message);
}
}
if(downloadStatus == DOWNLOAD_PAUSE){
Log.i("UpdateService", "download pause");
currentSize = totalSize;
startTime = 0;
isPaused = true;
break;
}
}
if(updateTotalSize == -1){
downloadStatus = DOWNLOAD_COMPLETE;
stateChanged();
isDownloadSucc = true;
//updateNotification.setLatestEventInfo(UpdateService.this, "�������", String.valueOf(downLoadPercent) + "%", updatePendingIntent);
//updateNotificationManager.notify(0, updateNotification);
Message message = updateHandler.obtainMessage();
message.what = DOWNLOAD_COMPLETE;
updateHandler.sendMessage(message);
}
}catch(Exception e){
downloadStatus = DOWNLOAD_FAIL;
stateChanged();
e.printStackTrace();
throw new Exception("fail!");
}finally {
if(is != null) {
is.close();
}
if(updateFileOs != null) {
updateFileOs.close();
}
// if(httpConnection != null) {
// httpConnection.disconnect();
// }
if(client != null){
client.getConnectionManager().shutdown();
}
}
return isDownloadSucc;
}
// Notify observers that this download's status has changed.
private void stateChanged() {
setChanged();
notifyObservers();
}
}
private void openFile(String fileName) {
File file = new File(fileName);
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
}
}