501 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			501 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| package com.novelbook.android.service;
 | |
| 
 | |
| import android.app.IntentService;
 | |
| import android.content.Intent;
 | |
| import android.os.Handler;
 | |
| import android.os.Message;
 | |
| import android.text.TextUtils;
 | |
| import android.util.Log;
 | |
| 
 | |
| import com.novelbook.android.db.Chapter;
 | |
| import com.novelbook.android.db.DownloadTask;
 | |
| import com.novelbook.android.db.SiteRule;
 | |
| import com.novelbook.android.netutils.HttpMethods;
 | |
| import com.novelbook.android.utils.BookUtil;
 | |
| import com.novelbook.android.utils.NovelParseUtil;
 | |
| 
 | |
| import org.json.JSONException;
 | |
| import org.json.JSONObject;
 | |
| import org.litepal.LitePal;
 | |
| 
 | |
| import java.io.File;
 | |
| import java.io.FileOutputStream;
 | |
| import java.io.IOException;
 | |
| import java.io.OutputStreamWriter;
 | |
| import java.util.ArrayList;
 | |
| import java.util.Date;
 | |
| import java.util.HashMap;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| import java.util.concurrent.ConcurrentHashMap;
 | |
| 
 | |
| import okhttp3.Call;
 | |
| import okhttp3.Callback;
 | |
| import okhttp3.Request;
 | |
| import okhttp3.Response;
 | |
| import okhttp3.ResponseBody;
 | |
| 
 | |
| 
 | |
| public class ServiceDownloadIntent extends IntentService {
 | |
|     private static final String TAG ="ServiceDownload" ;
 | |
| 
 | |
|     private   final String storagePath = BookUtil.storagePath;
 | |
|     private   final String cachedPath = BookUtil.cachedPath;
 | |
|     private   final String chapterPath = BookUtil.chapterPath;
 | |
| 
 | |
|     public final String EXTR_TASKID ="taskId";
 | |
|     public final String EXTR_OFFSET ="offset"; //多线程下载,每个线程取章节偏移数量
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
|    // public ServiceDownload(String name) {
 | |
|   //      super(name);
 | |
|   //  }
 | |
|     public ServiceDownloadIntent() {
 | |
|         super("ServiceDownload");
 | |
|     }
 | |
| 
 | |
|      private Map<Integer,SiteRule>  siteRuleMap = new HashMap<Integer,SiteRule>()  ;  // key = novelId
 | |
|      private DownloadTask processingTask  ;
 | |
|      private int taskIndex=0;
 | |
|      private int chaptIndex=0;
 | |
| 
 | |
|     private Map<Integer ,List<Chapter>> tasksMap = new  ConcurrentHashMap<Integer, List<Chapter>>();// key = taskId
 | |
| 
 | |
|     @Override
 | |
|     public void onCreate() {
 | |
|         super.onCreate();
 | |
|         Log.d(TAG,"test service onCreate...");
 | |
| 
 | |
|         /*
 | |
|         downloadTasks =LitePal.where("status = ?","0").find(DownloadTask.class);
 | |
|         for(DownloadTask dt :downloadTasks){
 | |
|             List<Chapter> chps =Chapter.getUnCachedChapters(dt.getNovelId(),dt.getDomain());
 | |
|             if(chps.size()>0) {
 | |
|                 SiteRule sr = SiteRule.getSiteRuleByDomain(dt.getDomain());
 | |
|                 siteRuleMap.put(dt.getNovelId(), sr);
 | |
|                 tasksMap.put(dt.getId(), chps);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         for(DownloadTask tmp: downloadTasks){
 | |
|             Log.d(TAG, String.format("test service task list : %s",tmp.getId()));
 | |
|         }
 | |
|         */
 | |
| 
 | |
| 
 | |
|     }
 | |
|     @Override
 | |
|     public void onStart(Intent intent, int startId) {
 | |
|         super.onStart(intent, startId);
 | |
|         Log.d(TAG,"test service onStart");
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public int onStartCommand(Intent intent, int flags, int startId) {
 | |
|         Log.d(TAG,"test service onStartCommand");
 | |
|         return super.onStartCommand(intent, flags, startId);
 | |
| 
 | |
|     }
 | |
| 
 | |
|     @Override
 | |
|     public void onDestroy() {
 | |
|         Log.d(TAG,"test service onDestroy");
 | |
|         super.onDestroy();
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
|     private List<DownloadTask> downloadTasks = new ArrayList<DownloadTask>();
 | |
| 
 | |
|     int cancelId =0;
 | |
|     @Override
 | |
|     protected void onHandleIntent( Intent intent) {
 | |
|         Log.d(TAG,"test service onHandleIntent...begin");
 | |
| 
 | |
|         String key ="taskId";
 | |
|         int taskId =0;
 | |
| 
 | |
|         if(intent.hasExtra(key)){
 | |
|             taskId=	intent.getExtras().getInt(key);
 | |
|             DownloadTask dt = LitePal.find(DownloadTask.class,taskId);
 | |
| 
 | |
|             if(intent.hasExtra("start")){
 | |
|                 if(!intent.getBooleanExtra("start",true)){
 | |
|                     cancelId = taskId;
 | |
|                     stopTask(taskId);
 | |
|                 }else{
 | |
|                     startNewTask(dt);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
| 
 | |
|         }
 | |
|         else{
 | |
|             if(downloadTasks.size()==0) {
 | |
|                 List<DownloadTask> tmp = LitePal.findAll(DownloadTask.class);
 | |
|                 taskIndex=0;
 | |
|                 for(DownloadTask dt :tmp) {
 | |
|                     startNewTask(dt);
 | |
|                 }
 | |
| 
 | |
| 
 | |
|             }
 | |
| 
 | |
| 
 | |
|           /*
 | |
|              if(processingTask==null) {
 | |
|                 startTask();
 | |
|             }*/
 | |
|         }
 | |
|         Log.d(TAG,"test service onHandleIntent...over");
 | |
|     }
 | |
| 
 | |
|     private void stopTask(int taskId) {
 | |
|         for(DownloadTask dt : downloadTasks){
 | |
|             if(dt.getId() == taskId){
 | |
|                 dt.setDownSatus(DownloadTask.DownStatus.暂停下载);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         startTask();
 | |
|     }
 | |
| 
 | |
|     Handler handler = new Handler()  {
 | |
|         @Override
 | |
|         public void handleMessage(Message msg) {
 | |
|             if(msg.what ==1){
 | |
|                 startTask();
 | |
|             }else if(msg.what==2){
 | |
| 
 | |
|                 if( downloadTasks.get(taskIndex).getDownSatus() == DownloadTask.DownStatus.暂停下载){
 | |
|                     return;
 | |
|                 }
 | |
|                 if(tasksMap.get(processingTask.getId())==null){
 | |
|                     return;
 | |
|                 }
 | |
|                 Log.d(TAG,String.format("%s start new chapt download---- taskId :%s, chapter count %s,chaptIndex %s",TAG
 | |
|                         , processingTask.getId(),
 | |
|                         tasksMap.get(processingTask.getId()).size(),chaptIndex ));
 | |
| 
 | |
| 
 | |
|                 Intent broadcastIntent = new Intent();
 | |
|                 broadcastIntent.setAction("ServiceDownload.ChapterContent.finished");
 | |
|                 broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
 | |
|                 broadcastIntent.putExtra("progress", processingTask.getFinishedChpats());
 | |
|                 broadcastIntent.putExtra("novelId", processingTask.getNovelId());
 | |
|                 broadcastIntent.putExtra("taskId", processingTask.getId());
 | |
|                 sendBroadcast(broadcastIntent);
 | |
| 
 | |
| 
 | |
|                 if( tasksMap.get(processingTask.getId()).size()-1 > chaptIndex){
 | |
| 
 | |
|                     chaptIndex++;
 | |
| 
 | |
|                 }else{
 | |
|                     Log.d(TAG,String.format("%s task done ---- taskId :%s, chapter count %s,chaptIndex %s",TAG , processingTask.getId(),
 | |
|                             tasksMap.get(processingTask.getId()).size(),chaptIndex ));
 | |
|                       //章节全部处理完毕了
 | |
|                         processingTask.setStatus(1);
 | |
|                         processingTask.update(processingTask.getId());
 | |
| 
 | |
|                         tasksMap.remove(processingTask.getId()); //会不会线程冲突?
 | |
| 
 | |
|                         startTask();
 | |
|                 }
 | |
| 
 | |
|                 doDownloadContent();
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|         };
 | |
| 
 | |
| 
 | |
| 
 | |
|     private void startTask() {
 | |
| 
 | |
|         if(processingTask!=null) {
 | |
|             processingTask.update(processingTask.getId());
 | |
|         }
 | |
| 
 | |
| 
 | |
| 
 | |
|         if(downloadTasks.size() <=taskIndex){
 | |
|             processingTask =null;
 | |
|             Log.d(TAG,"No task to download.");
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         processingTask =    downloadTasks.get(taskIndex);
 | |
|         if(processingTask.getDownSatus()== DownloadTask.DownStatus.暂停下载){
 | |
|             taskIndex++;
 | |
|             startTask();
 | |
|             return;
 | |
|         }
 | |
|         processingTask.setDownSatus(DownloadTask.DownStatus.正在下载);
 | |
|         chaptIndex=0;
 | |
|         doDownloadContent();
 | |
|         if(taskIndex < downloadTasks.size()-1){
 | |
|             taskIndex++;
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
| 
 | |
|     void doDownloadContent(){
 | |
| 
 | |
|         Log.d(TAG, String.format("ServiceDowload--- taskId: %s ",processingTask.getId()));
 | |
|         List<Chapter> chps = tasksMap.get(processingTask.getId());
 | |
|         if(chps!=null && chps.size()>0) {
 | |
|             Chapter chapter = chps.get(chaptIndex);
 | |
| 
 | |
|             if (TextUtils.isEmpty(chapter.getChapterPath())) {
 | |
|                 try {
 | |
|                     ServiceDownload(chapter);
 | |
|                 } catch (JSONException e) {
 | |
|                     e.printStackTrace();
 | |
|                 } catch (InterruptedException e) {
 | |
|                     e.printStackTrace();
 | |
|                // } catch (IOException e) {
 | |
|               //      e.printStackTrace();
 | |
|                 }
 | |
| 
 | |
|             } else {
 | |
|                 handler.sendEmptyMessage(2);
 | |
|             }
 | |
|         }else{
 | |
|             handler.sendEmptyMessage(2);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|       void startNewTask(DownloadTask dt){
 | |
| 
 | |
| 
 | |
| 
 | |
|         if(dt!=null){
 | |
|             List<Chapter> chps = Chapter.getUnCachedChapters(dt.getId() );
 | |
|             if(chps==null || chps.size()==0){
 | |
|                 return;
 | |
|             }
 | |
|             SiteRule siteRule = SiteRule. getSiteRuleByDomain(dt.getDomain());
 | |
|             if(siteRule==null){
 | |
|                 //to do get siterule from web
 | |
|                 Log.d(TAG, String.format("没找到site rule: %s",dt.getDomain()));
 | |
|             }else {
 | |
|                 siteRuleMap.put(dt.getNovelId(),siteRule);
 | |
| 
 | |
|                 downloadTasks.add(dt);
 | |
| 
 | |
|                 for(DownloadTask tmp: downloadTasks){
 | |
|                     Log.d(TAG, String.format("test service task list : %s",tmp.getId()));
 | |
|                 }
 | |
| 
 | |
| 
 | |
|                 tasksMap.put(dt.getId(), chps);
 | |
|                 if(taskIndex==0) {
 | |
|                     startTask();
 | |
|                   //  handler.sendEmptyMessage(1);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         /*
 | |
|         new Thread() {
 | |
| 
 | |
|             @Override
 | |
|             public void run() {
 | |
| 
 | |
| 
 | |
| 
 | |
|             }
 | |
|         }.start();
 | |
| 
 | |
|         */
 | |
|     }
 | |
|     private void ServiceDownload( Chapter chapter ) throws JSONException, InterruptedException {
 | |
| 
 | |
|         int msg =2;
 | |
| 
 | |
|         String url = chapter.getChapterUrl();
 | |
|         if( TextUtils.isEmpty( url)){
 | |
|             handler.sendEmptyMessage(msg);
 | |
|             return ;
 | |
|         }
 | |
|         long startTime= new Date().getTime();
 | |
|         Log.d(TAG,String.format("ServiceDowload----start download %s from %s",   chapter.getChapterName()  ,url ));
 | |
| 
 | |
| 
 | |
| 
 | |
|         //  Log.d( "ServiceDowload",String.format("ServiceDowload isDownloadChapt: %s",isDownloadChapt));
 | |
|         JSONObject siteJson = new JSONObject();
 | |
|         siteJson.put("chapterContentRegex", siteRuleMap.get(chapter.getNovelId()).getChapterContentRegex());
 | |
|         siteJson.put("chapterContentDumpRegex",  siteRuleMap.get(chapter.getNovelId()).getChapterContentDumpRegex());
 | |
|         Request request = getTagRequest(url);
 | |
|         HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
 | |
|             @Override
 | |
|             public void onFailure(Call call, IOException e) {
 | |
| 
 | |
|                 handler.sendEmptyMessage(msg);
 | |
| 
 | |
|                 //  Log.d( "ServiceDowload",String.format("ServiceDowload fail, isDownloadChapt: %s",isDownloadChapt));
 | |
|                 e.printStackTrace();
 | |
|                 // throw new RuntimeException("Error during writing " + fileChapterName( index));
 | |
|             }
 | |
| 
 | |
|             @Override
 | |
|             public void onResponse(Call call, Response response){
 | |
|                 ResponseBody body = response.body();
 | |
|                 if (body != null ) {
 | |
|                     if(response.code()!=200){
 | |
|                         Log.d(TAG, "ServiceDowload----network failure returnCode " + response.code());
 | |
|                         //  setDownloadFlag(true);
 | |
|                         //  chaptDownStatus.put(index, BookUtil.DownloadStatus.failure);
 | |
|                         //   Log.d( "ServiceDowload",String.format("ServiceDowload error %s ,isDownloadChapt: %s",  response.code(),isDownloadChapt));
 | |
|                         handler.sendEmptyMessage(msg);
 | |
|                         return;
 | |
|                     }
 | |
| 
 | |
|                     try {
 | |
|                         String bodyStr = body.string();
 | |
|                         String title = chapter.getChapterName();
 | |
|                         String chapterContent = title+ "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson);
 | |
|                         char[] buf = chapterContent.toCharArray();
 | |
|                         File file = new File(fileChapterName(chapter));
 | |
|                         file.createNewFile();
 | |
| 
 | |
|                         final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(chapter)), "utf-8");//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
 | |
|                         writer.write(buf);
 | |
|                         writer.close();
 | |
|                         Log.d( "ServiceDowload",String.format("ServiceDowload file created:  %s",  file.getPath()));
 | |
|                         processingTask.setFinishedChpats(processingTask.getFinishedChpats()+1);
 | |
|                         processingTask.update(processingTask.getId());
 | |
|                         Thread.sleep(siteRuleMap.get(chapter.getNovelId()).getMiniInterval4AccessChapter());
 | |
|                         //  setDownloadFlag(true);
 | |
|                     } catch (IOException | JSONException | InterruptedException e) {
 | |
|                         e.printStackTrace();
 | |
|                         //  throw new RuntimeException("Error during writing " + fileChapterName( index));
 | |
|                     }
 | |
|                     finally {
 | |
|                         body.close();
 | |
| 
 | |
| 
 | |
|                         //  setDownloadFlag(true);
 | |
|                     }
 | |
| 
 | |
|                     chapter.setChapterPath(fileChapterName(chapter));
 | |
|                     chapter.update(chapter.getId());
 | |
|                     handler.sendEmptyMessage(msg);
 | |
| 
 | |
|                     //setDownloadFlag(true);
 | |
|                     //   chaptDownStatus.put(index, BookUtil.DownloadStatus.success);
 | |
|                     Log.d(TAG,String.format("ServiceDowload---- finished download %s, cost time %s ,content path %s ",  chapter.getChapterName(),  new Date().getTime() -startTime ,chapter.getChapterPath()   ));
 | |
| 
 | |
|                 }
 | |
|             }
 | |
|         });
 | |
| 
 | |
| 
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 直接
 | |
|      * @param chapter
 | |
|      * @throws JSONException
 | |
|      * @throws InterruptedException
 | |
| 
 | |
| 
 | |
|     private void ServiceDownload2( Chapter chapter ) throws IOException, JSONException, InterruptedException {
 | |
| 
 | |
|         int msg = 2;
 | |
| 
 | |
|         String url = chapter.getChapterUrl();
 | |
|         if (TextUtils.isEmpty(url)) {
 | |
|             handler.sendEmptyMessage(msg);
 | |
|             return;
 | |
|         }
 | |
|         long startTime = new Date().getTime();
 | |
|         Log.d(TAG, String.format("ServiceDowload----start download %s from %s", chapter.getChapterName(), url));
 | |
| 
 | |
| 
 | |
|         //  Log.d( "ServiceDowload",String.format("ServiceDowload isDownloadChapt: %s",isDownloadChapt));
 | |
|         JSONObject siteJson = new JSONObject();
 | |
|         siteJson.put("chapterContentRegex", siteRuleMap.get(chapter.getNovelId()).getChapterContentRegex());
 | |
|         siteJson.put("chapterContentDumpRegex", siteRuleMap.get(chapter.getNovelId()).getChapterContentDumpRegex());
 | |
|         Request request = getTagRequest(url);
 | |
|         Response response = HttpMethods.getOkClient().newCall(request).execute();
 | |
|         ResponseBody body = response.body();
 | |
|         if (body != null) {
 | |
|             if (response.code() != 200) {
 | |
|                 Log.d(TAG, "ServiceDowload----network failure returnCode " + response.code());
 | |
|                 //  setDownloadFlag(true);
 | |
|                 //  chaptDownStatus.put(index, BookUtil.DownloadStatus.failure);
 | |
|                 //   Log.d( "ServiceDowload",String.format("ServiceDowload error %s ,isDownloadChapt: %s",  response.code(),isDownloadChapt));
 | |
|                 handler.sendEmptyMessage(msg);
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             try {
 | |
|                 String bodyStr = body.string();
 | |
|                 String title = chapter.getChapterName();
 | |
|                 String chapterContent = title + "\n" + NovelParseUtil.getChapterContent(bodyStr, siteJson);
 | |
|                 char[] buf = chapterContent.toCharArray();
 | |
|                 File file = new File(fileChapterName(chapter));
 | |
|                 file.createNewFile();
 | |
| 
 | |
|                 final OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileChapterName(chapter)), "utf-8");//"UTF-16LE"); // UTF-16LE 比 utf-8 文件小
 | |
|                 writer.write(buf);
 | |
|                 writer.close();
 | |
|                 Log.d("ServiceDowload", String.format("ServiceDowload file created:  %s", file.getPath()));
 | |
|                 processingTask.setFinishedChpats(processingTask.getFinishedChpats() + 1);
 | |
|                 processingTask.update(processingTask.getId());
 | |
|                 Thread.sleep(siteRuleMap.get(chapter.getNovelId()).getMiniInterval4AccessChapter());
 | |
|                 //  setDownloadFlag(true);
 | |
|             } catch (IOException | JSONException | InterruptedException e) {
 | |
|                 e.printStackTrace();
 | |
|                 //  throw new RuntimeException("Error during writing " + fileChapterName( index));
 | |
|             } finally {
 | |
|                 body.close();
 | |
| 
 | |
| 
 | |
|                 //  setDownloadFlag(true);
 | |
|             }
 | |
| 
 | |
|             chapter.setChapterPath(fileChapterName(chapter));
 | |
|             chapter.update(chapter.getId());
 | |
|             handler.sendEmptyMessage(msg);
 | |
| 
 | |
|             //setDownloadFlag(true);
 | |
|             //   chaptDownStatus.put(index, BookUtil.DownloadStatus.success);
 | |
|             Log.d(TAG, String.format("ServiceDowload---- finished download %s, cost time %s ,content path %s ", chapter.getChapterName(), new Date().getTime() - startTime, chapter.getChapterPath()));
 | |
| 
 | |
|         }
 | |
| 
 | |
| 
 | |
|     }
 | |
| */
 | |
| 
 | |
|     protected String fileChapterName(Chapter chapter ) {
 | |
|             return  getChapterPath(chapter.getNovelId()) +chapter.getDomain()+"/"+ chapter.getIndex() ;
 | |
| 
 | |
|     }
 | |
|     String getChapterPath(int novelId){
 | |
|         File file = new File(chapterPath +novelId);
 | |
|         if(!file.exists()){
 | |
|             file.mkdir();
 | |
|         }
 | |
|         return  chapterPath +novelId+"/";
 | |
|     }
 | |
| 
 | |
|     private Request getTagRequest(String url) {
 | |
|         return new  Request.Builder()
 | |
|                 .tag(processingTask.getNovelId()) //标记
 | |
|                 .url(url)
 | |
|                 // .header("User-Agent", "OkHttp Example")
 | |
|                 .build();
 | |
|     }
 | |
| 
 | |
| 
 | |
| 
 | |
| }
 |