昨天我发布了我的应用程序,我在手机上测试并按预期工作。当我的朋友使用3G而不是WiFi下载它时,我的应用程序无法下载所有内容,因此它崩溃了。我使用了一个运行AsyncTask的无头片段来下载内容(这是一些照片),我的猜测是它花了很多时间拍摄一些照片并跳过它们,抛出一些时间例外。我的问题是,如果我使用服务运行我的AsyncTask并下载内容而不是片段,这是否可以避免?
private ArrayList<Monument> processJsonData(JSONObject jsonObj) throws IOException{
try{
JSONArray posts=jsonObj.getJSONArray(TAG_POSTS);
ArrayList<Monument> monuments = new ArrayList<Monument>();
for (int i=0; i<posts.length(); i++){
JSONArray attachments = c.optJSONArray(TAG_ATTACHMENTS);
if(attachments!=null){
int lengthSize;
if(attachments.length()<3)
lengthSize=attachments.length();
else
lengthSize=3;
for(int j=0;j<lengthSize;++j){
JSONObject atta = attachments.getJSONObject(j);
JSONObject images = atta.optJSONObject(TAG_IMAGES);
if(images!=null){
JSONObject medium = images.getJSONObject(TAG_MEDIUM);
String url_image = medium.getString(TAG_URL_IMAGE);
String id = atta.getString("id");
String filename =title.replace(" ","")+id+".nomedia";
File destination = new File(MyApplication.getPhotoStorage() ,filename);
URL url = new URL (url_image);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destination);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
编辑所以我现在在代码中进行了这些更改我正在处理connectionTimeout异常,但我无法正常捕获
@Override
protected String doInBackground(String... args) {
JSONParser jParser = new JSONParser();
JSONObject jsonObj = jParser.getJSONFromUrl(url);
Log.d("check1",url);
try {
listOfObjects.addAll(processJsonData(jsonObj));
} catch (Exception e) {
e.printStackTrace();
onDownloadFailed(this);
} finally {
jsonObj=null;
}
return "done";
}
protected void onDownloadFailed(downloadUrl task) {
System.out.println(task.tag+" failed to download");
if(dtask1.cancel(true))
Log.d("TASK1", "Canceled");
if(dtask2.cancel(true))
Log.d("TASK2", "Canceled");
if(dtask3.cancel(true))
Log.d("TASK3", "Canceled");
if(dtask4.cancel(true))
Log.d("TASK4", "Canceled");
mCallbacks.onDownloadFailed();
}
private ArrayList<Monument> processJsonData(JSONObject jsonObj) throws IOException, SocketException, JSONException{
JSONArray attachments = c.optJSONArray(TAG_ATTACHMENTS);
if(attachments!=null){
int lengthSize;
if(attachments.length()<3)
lengthSize=attachments.length();
else
lengthSize=3;
for(int j=0;j<lengthSize;++j){
JSONObject atta = attachments.getJSONObject(j);
JSONObject images = atta.optJSONObject(TAG_IMAGES);
if(images!=null){
JSONObject medium = images.getJSONObject(TAG_MEDIUM);
String url_image = medium.getString(TAG_URL_IMAGE);
String id = atta.getString("id");
String filename =title.replace(" ","")+id+".nomedia";
File destination = new File(MyApplication.getPhotoStorage() ,filename);
try{
URL url = new URL (url_image);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destination);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
}catch (SocketException e) {
throw new SocketTimeoutException();
}
}
}
}
答案 0 :(得分:0)
没有。这是不可避免的。您不能指望连接持续很长时间。手机上可能发生任何事情(电池电量耗尽,网络信号丢失等)
您必须对应用进行编码,以便正确检查其是否具有所有可用资源,并重试(或更好地,恢复)失败的下载。
为了增加你的机会,在相对较小的下载而不是大文件中打破你的资源。然后,当使用3G时,用户不必从头开始全部下载。
答案 1 :(得分:0)
好吧,所以我不太了解JSON,但这不应该影响这个答案,我不会想。看起来您的问题可以通过better use of Exception
handling来解决。
目前你根本没有真正处理异常,只是抓住它并打印堆栈跟踪。此外,因为整个方法都在一个try{ }
语句中,所以如果在处理任何一个附件时出现问题,则该方法将退出。相反,您可以在try{ }
循环中包含for
块。这样,如果任何一个循环块失败(由于连接不稳定),您可以使用catch块j--;
然后Thread.sleep(4000);
。这样,当循环中抛出异常时它将被捕获,循环将被跳回以再次尝试相同的部分,并且将暂停以等待更好的连接。
示例(未测试);
for (int j = 0; j < lengthSize; ++j) {
try{
JSONObject atta = attachments.getJSONObject(j);
JSONObject images = atta.optJSONObject(TAG_IMAGES);
if (images != null) {
JSONObject medium = images.getJSONObject(TAG_MEDIUM);
String url_image = medium.getString(TAG_URL_IMAGE);
String id = atta.getString("id");
String filename = title.replace(" ", "") + id + ".nomedia";
File destination = new File(MyApplication.getPhotoStorage(), filename);
URL url = new URL(url_image);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destination);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
}
}catch (Exception e){
Thread.sleep(4000);
j--;
}
}
您可能还想创建一个计数器,以查看已尝试的次数。如果代码进行了太多尝试,那么您可以假设它永远不会工作并从方法返回。
我希望这会有所帮助。让我知道你是怎么过的。
另外,除此之外你永远不应该抓住Exception
。最好能够捕获您期望的特定异常,以便您可以根据Exception
子类型以不同方式处理它们。你可能不想抓住RunTimeException
并试图在没有有效方法的情况下处理它。