Сегодня, когда писал для своего сайта новый учебный пример, тренируясь на кошках, неожиданно столкнулся с одной проблемой на ровном месте. В коде программы нужно было реализовать загрузку изображения из интернета и сохранить его на SD-карточку. На первый взгляд задача не представляла трудностей, но проект вдруг стал выдавать ошибку.
Здесь надо сделать небольшое отступление. Я начал изучать программирование под Android сравнительно недавно и начинал с версии Android 2.3, так как у меня был телефон с такой же версией. И все проекты пробовал на эмуляторе под этой же версией. Пару месяцев назад для моего Samsung Galaxy SII вышло обновление до ICS (Android 4.0) и я стал создавать новые проекты под новую версию, а также переписывать свои учебные примеры под новую платформу. Периодически в Eclipse при загрузке старых проектов попадались строчки кода с зачёркнутыми методами. Было ясно, что данный метод устарел и нужно перечитать документацию.
В моём последнем случае ничего не подчёркивалось, а природа ошибки была не совсем ясна. В одном из моих уроков использовался схожий пример загрузки изображения из сети в ImageView, который прекрасно работал раньше в Android 2.3. Ради интереса, я запустил этот пример под эмулятором Android 4.0, будучи абсолютно уверенный в работоспособности примера. Но не тут-то было, и этот пример не запускался. Заменив в примере одну строчку
txtUrl.setText(e.toString());
я получил описание ошибки — android.os.NetworkOnMainThreadException. Дальше было проще. Имея эту информацию и призвал на помощь Гугл, я выяснил, что, начиная с Android 3.0 правила немного изменились. Теперь нельзя обращаться к сетевым ресурсам в основном потоке активности. Поэтому пришлось переделывать пример на новый лад.
package ru.alexanderklimov.imagefrominet;
import java.io.InputStream;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
public class ImageFromInetActivity extends Activity {
private ImageView imgView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imgView = (ImageView) findViewById(R.id.imgView);
// Веб-адрес картинки
String url = "http://developer.alexanderklimov.ru/android/images/android_cat.jpg";
// show The Image
new DownloadImageTask(imgView)
.execute(url);
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
}
В исправленном варианте пример заработал. Возможно, код ещё требует доработки, но уже ясно в каком направлении нужно двигаться.
Наверняка, компании и серьёзные разработчики в курсе этой проблемы. Решение проблемы уже описано и в документации и на StackOverfow.com. В моём случае для меня это стало сюрпризом, так как в рабочих проектах не было необходимости использовать загрузку изображений из интернета. И думается, что для многих программистов-любителей это может стать головной болью. Представьте себе ситуацию, что в вашем приложении используется загрузка картинки или другого файла из интернета. И часть пользователей, которые обновились до ICS, начинает жаловаться, что ничего не работает. Другая часть пользователей с такой же моделью телефона будет утверждать, что всё прекрасно работает. Догадаться про источник проблемы будет достаточно затруднительно.
Вывод: Пересмотрите свои старые проекты на предмет работоспособности под Android 4.0. Буквально вчера обновилась статистика устройств под разные версии Android и Android 4 уже обогнала версию 2.1. Вполне допускаю, что к концу года четверка подвинет и версию 2.2. Поэтому нужно уже сейчас задуматься об этой проблеме.
P.S. Во время опытов при решении проблемы ни одно животное не пострадало.
Автор: tehnolog