Pull to refresh

Пересмотрите старые проекты для Android 4.0

Development for Android *
Сегодня, когда писал для своего сайта новый учебный пример, тренируясь на кошках, неожиданно столкнулся с одной проблемой на ровном месте. В коде программы нужно было реализовать загрузку изображения из интернета и сохранить его на 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);
		}
	}
}




В исправленном варианте пример заработал. Возможно, код ещё требует доработки, но уже ясно в каком направлении нужно двигаться.
Наверняка, компании и серьёзные разработчики в курсе этой проблемы. Решение проблемы уже описано и в документации и на StackOverflow.com. Профессионалы не пишут длительные операции в основном потоке и они и не заметят проблемы вообще. В моём случае для меня это стало сюрпризом, так как в рабочих проектах не было необходимости использовать загрузку изображений из интернета, а вот в учебном примере такой «неправильный» код попался. И думается, что для многих программистов-любителей это может стать головной болью. Представьте себе ситуацию, что в вашем приложении используется загрузка картинки или другого файла из интернета. И часть пользователей, которые обновились до ICS, начинает жаловаться, что ничего не работает. Другая часть пользователей с такой же моделью телефона будет утверждать, что всё прекрасно работает. Догадаться про источник проблемы будет достаточно затруднительно.

Вывод: Пересмотрите свои старые проекты на предмет работоспособности под Android 4.0. Буквально вчера обновилась статистика устройств под разные версии Android и Android 4 уже обогнала версию 2.1. Вполне допускаю, что к концу года четверка подвинет и версию 2.2. Поэтому нужно уже сейчас задуматься об этой проблеме.

P.S. Во время опытов при решении проблемы ни одно животное не пострадало.
Tags:
Hubs:
Total votes 63: ↑41 and ↓22 +19
Views 12K
Comments 29
Comments Comments 29

Posts