내 나쁜 영어 실례 바랍니다 내 설명을 이해할 수 있기를 바랍니다.동시에 많은 업로드 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();
}
}
}
}
_ 수십 개의 대기열을 생성하고 있으며 대기열을 실행하라는 호출도 표시되지 않습니다. _ 그 의미는 무엇입니까? 내가 실행 대기열을 만드는 곳은 어디입니까? – Laire
에서 onPostExecute. 일반적으로 요청 당 하나가 아닌 앱당 하나의 큐가 있습니다. –
위의 편집을 추가했습니다. 대기열에 하나 이상의 응답을 추가하려고 시도하지만 작동하지 않습니다. – Laire