0

내 나쁜 영어 실례 바랍니다 내 설명을 이해할 수 있기를 바랍니다.동시에 많은 업로드 AsyncTask에

나는 내 서버와 통신하는 앱 개발 중이다. 그것은 다른 작업을하고 있습니다. 그 중 하나는 내 스마트 폰에서 내 서버로 사진을 업로드하는 것입니다. 내 응용 프로그램이 메모리와 대역폭을 최소화하면서 백그라운드에서이를 수행하기를 바랍니다.

기본적으로 작동하지만 많은 새로운 사진이있는 경우 많은 AsyncTask가 동시에 메모리와 대역폭을 줄일 수 있습니다.

먼저 30 분마다 내 사진 스캐너를 시작하는 BroadcastReceiver를 사용합니다. 외부 저장소가 읽을 수있는 경우 검사기 검사, WIFI가 켜져 있고 인터넷 연결이있는 경우 검사합니다.

사실이면 이미 업로드 된 사진의 목록을 데이터베이스에서 쿼리합니다.

그런 다음 MediaStore 라이브러리의 모든 사진을 요청하고 최소값 (크기, 높이, 너비)을 확인하고 사진이 업로드되지 않은 경우 확인하십시오. 모든 것이 확인되면, 이미지 크기를 조정하기위한 AsyncTask를 시작하고 업로드를 :

public class Scanner { 

    private Context context; 
    private PicDAO picDAO; 
    private Helper helper; 

    public Scanner(Context context) { 
     this.context = context; 
     picDAO = new PicDAO(context); 
     helper = new Helper(context); 
    } 

    public void startScan(){ 
     if(helper.isExternalStorageReadable() 
       && helper.isWifiOn() 
       && helper.checkInternet()){ 
      HashMap<Integer, String> pics = picDAO.picsHashMap(); 
      Cursor mCursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,null,null,null,MediaStore.Images.Media.DEFAULT_SORT_ORDER); 
      if(mCursor != null){ 
       mCursor.moveToFirst(); 
       while(!mCursor.isAfterLast()) { 
        PicClass pic = new PicClass(
          mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media._ID)), 
          mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)), 
          mCursor.getString(mCursor.getColumnIndex(MediaStore.Images.Media.DATA)), 
          mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.WIDTH)), 
          mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.HEIGHT)), 
          mCursor.getInt(mCursor.getColumnIndex(MediaStore.Images.Media.SIZE)), 
          context 
        ); 
        if(pic.getSize() > 25000 
          && pic.getHeight() > 200 
          && pic.getWidth() > 200 
          && (pics.get(pic.getIdent()) == null || !pics.get(pic.getIdent()).equals(pic.getDisplay_name())) 
          ){ 
         CreateThumb createThumb = new CreateThumb(context); 
         createThumb.execute(new PicClass[]{pic}); 
        } 
        mCursor.moveToNext(); 
       } 
       mCursor.close(); 
      } 
     } 
    } 
} 

을 creatThumb는 이미지 크기를 조정보고합니다 (발리 라이브러리 사용) 업로드를 시작합니다

공용 클래스 CreateThumb은 AsyncTask를 확장을

,691,363 : 내 서버에 {

private Context context; 

public CreateThumb(Context context) { 
    this.context = context; 
} 

@Override 
protected PicClass doInBackground(PicClass... pics) { 
    Helper helper = new Helper(context); 
    String encodedString = ""; 
    if(helper.isWifiOn() && helper.checkInternet()){ 
     double dWidth = 1000; 
     double dHeight = 1000; 
     if(pics[0].getWidth() < (int) dWidth && pics[0].getHeight() < (int) dHeight){ 
      dWidth = pics[0].getWidth(); 
      dHeight = pics[0].getHeight(); 
     }else{ 
      if (pics[0].getWidth() > pics[0].getHeight()){ 
       double div = pics[0].getWidth()/dWidth; 
       dHeight = pics[0].getHeight()/div; 
      }else{ 
       double div = pics[0].getHeight()/dHeight; 
       dWidth = pics[0].getWidth()/div; 
      } 
     } 
     int width = (int) dWidth; 
     int height = (int) dHeight; 
     BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
     Bitmap bitmap = BitmapFactory.decodeFile(pics[0].getPath(),bmOptions); 
     Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap,width,height,0); 
     ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
     thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, stream); 
     byte[] byte_arr = stream.toByteArray(); 
     encodedString = Base64.encodeToString(byte_arr, 0); 
    } 
    pics[0].setThumb_file(encodedString); 
    return pics[0]; 
} 
@Override 
protected void onPostExecute(final PicClass pic) { 
    if(!pic.getThumb_file().equals("")){ 
     RequestQueue queue = Volley.newRequestQueue(context); 
     String url ="http://example.de/upload.php"; 
     StringRequest postRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>(){ 
      @Override 
      public void onResponse(String response) { 
       if(response.equals("OK")){ 
        PicDAO picDAO = new PicDAO(context); 
        picDAO.savePic(pic); 
       } 
      } 
     }, 
      new Response.ErrorListener() { 
       @Override 
       public void onErrorResponse(VolleyError error) {} 
      } 
     ){ 
      @Override 
      protected Map<String, String> getParams() { 
       Map<String, String> params = new HashMap<>(); 
       params.put("img",pic.getThumb_file()); 
       params.put("filename",pic.getDisplay_name() + ".jpg"); 
       return params; 
      } 
     }; 
     queue.add(postRequest); 
    } 
} 

}

스크립트를 (210)

<?php 
    $base = $_POST['img']; 
    $filename = $_POST['filename']; 
    $binary = base64_decode($base); 
    $file = fopen('uploadedimages/'.$filename, 'wb'); 
    fwrite($file, $binary); 
    fclose($file); 
    echo "OK"; 

문제는 그 많은 새로운 사진에있을 때,이 장치와 인터넷 연결 속도를 느리게하고, 나는이 오류를 얻을 수 있습니다 :

W/예술 : 모든 스레드 걸린 일시 : 278.260ms D/발리 [2,790] BasicNetwork.logSlowRequests : HTTP 요청에 대한 응답 < = [] http://example.de/upload.php 0x8a9f5792 NORMAL 1> [수명 = 3447] [사이즈 = 2], [RC = 200], [RetryCount 값 = 1]

내 코드를 최적화하거나 동시에 많은 업로드를 방지하려면 어떻게해야합니까?

편집 나는 스캐너 부분을 다시 내가 요청을 추가 할 경우 단지 하나의 대기열을 사용하려고했습니다. 하지만 작동하지 않는 것 같습니다. 하나의 그림 만 있으면 작동하지만 스크립트가 요청보다 많은 정보를 추가하면 서버에서 첫 번째 그림 만 응답을 얻지 못합니다.

public class Scanner { 

    private Context context; 
    private PicDAO picDAO; 
    private Helper helper; 

    public Scanner(Context context) { 
     this.context = context; 
     picDAO = new PicDAO(context); 
     helper = new Helper(context); 
    } 

    public void startScan(){ 
     if(helper.isDeviceReady()){ 
      Cursor mCursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,null,null,null,MediaStore.Images.Media.DEFAULT_SORT_ORDER); 
      if(mCursor != null){ 
       final RequestQueue mRequestQueue = Volley.newRequestQueue(context); 
       mCursor.moveToFirst(); 
       while(!mCursor.isAfterLast()) { 
        final PicClass pic = new PicClass(mCursor, context); 
        if(pic.checkSize() && !picDAO.picExist(pic)){ 
         BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
         Bitmap bitmap = BitmapFactory.decodeFile(pic.getPath(),bmOptions); 
         Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap,pic.getNewSize()[0],pic.getNewSize()[1],0); 
         ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
         thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, stream); 
         byte[] byte_arr = stream.toByteArray(); 
         pic.setThumb_file(Base64.encodeToString(byte_arr, 0)); 
         StringRequest postRequest = new StringRequest(Request.Method.POST, "http://example.de/upload.php", new Response.Listener<String>(){ 
          @Override 
          public void onResponse(String response) { 
           Log.d("DEBUG",response); 
           if(response.equals("OK")){ 
            PicDAO picDAO = new PicDAO(context); 
            picDAO.savePic(pic); 
           } 
          } 
         }, 
           new Response.ErrorListener() { 
            @Override 
            public void onErrorResponse(VolleyError error) { 
             VolleyLog.e("Error: ", error.getMessage()); 
            } 
           } 
         ){ 
          @Override 
          protected Map<String, String> getParams() { 
           Map<String, String> params = new HashMap<>(); 
           params.put("img",pic.getThumb_file()); 
           params.put("filename",pic.getDisplay_name() + ".jpg"); 
           return params; 
          } 
         }; 
         mRequestQueue.add(postRequest); 
        } 
        mCursor.moveToNext(); 
       } 
       mCursor.close(); 
      } 
     } 
    } 
} 

답변

0

어떻게 내 코드를 최적화하거나 나는 많은 업로드한다는 것을 방지 할 수 있습니다 동시에

내가 시간과 큐에 하나의 작업을 실행 IntentService를 사용하는 찬성 AsyncTask를 드롭 것

다른 모든 것.물론 전체 프로세스는 보이지 않는 것처럼 사소하지는 않으므로 Android Priority Job Queue과 같은 전용 라이브러리를 사용하는 것이 더 좋을 것입니다.

0

글쎄, 시작할 때마다 업로드 할 때마다 새로운 요청 대기열을 만들지 마십시오. 대기열에 대한 아이디어는 여러 요청을 추가 한 다음 대기열을 실행하고 Volley가 한 번에 작은 그룹의 요청을 천천히 처리하도록합니다. 수십 개의 대기열을 만들고 있고 대기열을 실행하라는 호출도 없습니다.

또한 AsyncTask보다는 Thread를 사용하고 싶습니다. AsyncTasks는 하나 여야합니다. 사실이 많은 작업을 사용하면 작업이 필요할 수있는 다른 모든 것들을 굶주리고 있습니다. 왜냐하면 그들은 공통의 스레드를 공유하기 때문입니다.

+0

_ 수십 개의 대기열을 생성하고 있으며 대기열을 실행하라는 호출도 표시되지 않습니다. _ 그 의미는 무엇입니까? 내가 실행 대기열을 만드는 곳은 어디입니까? – Laire

+0

에서 onPostExecute. 일반적으로 요청 당 하나가 아닌 앱당 하나의 큐가 있습니다. –

+0

위의 편집을 추가했습니다. 대기열에 하나 이상의 응답을 추가하려고 시도하지만 작동하지 않습니다. – Laire