Поиск по сайту
Результаты поиска по тегам 'app'.
Найдено 2 результата
-
[Поддержка] Приложение для сайта / App for website
buslikdrev опубликовал теме в Модули и дополнения
40 Завантажити / Придбати розширення Приложение для сайта / App for website Название модуля: Приложение для сайта - "App for website"Версия модуля: 1.0Тип лицензии: Full (полная версия)Тип установки: ocmodЯзык: Беларуская мова, English, Русский язык, Українська моваДата создания: 2.12.2020 Был протестирован на: OpenCart.pro 2.1.0.2.2 и 2.3.0.2.6, OpenCart-"Русская сборка" 2.1.0.2 (rs1), 2.3.0.2 (rs6) и 3.0.2.0 (rs3), ocStore 2.1.0.2.1, 2.3.0.2.3 и 3.0.2.0 - шаблон (default)Название архива: App for website v1.0 Full OpenCart 2.X-3.1.X.zip (wikipedia) Прогрессивное web-приложение (англ. progressive web app, PWA) — технология в web-разработке, которая визуально и функционально трансформирует сайт в приложение (мобильное приложение в браузере). Статистика говорит о том, что 66 % пользователей не скачивают ни одного приложения в месяц (данные comScore от 2014 года — в среднем за три месяца). Большую часть своего времени — примерно 85 % — пользователь проводит в пяти любимых приложениях. Как правило, это мессенджеры, соцсети, видеохостинги. При этом мобильный браузер также во многом не является приоритетной формой выхода в Интернет. По данным comScore, в 2017 году пользователи смартфонов и планшетов потратили 87 % своего времени на приложения — по сравнению с 13 % в браузере. PWA является гибридным решением и позволяет открыть приложение с помощью мобильного браузера. При этом полностью сохраняется функционал нативного приложения: отправка push-уведомлений; работа в режиме офлайн; доступ к аппаратному обеспечению устройства (с ограничениями); установка ярлыка (иконки) на рабочий стол мобильного устройства, визуально не отличающегося от ярлыка нативного приложения, и пр. ОПИСАНИЕ Модуль предназначен для возможности использования технологии на чистом JavaScript (без левых сервисов) и возможностью асинхронной загрузки: ==ПРИЛОЖЕНИЕ== - ServiceWorker ( developer.mozilla.org/ru/docs/Web/API/Service_Worker_API, caniuse.com/?search=ServiceWorker ); - Manifest ( developer.mozilla.org/ru/docs/Web/Manifest, developer.mozilla.org/ru/docs/Mozilla/Add-ons/WebExtensions/manifest.json, developer.mozilla.org/en-US/docs/Web/Progressive_web_apps, caniuse.com/?search=manifest ); - Add to home screen - A2HS ( developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Add_to_home_screen, caniuse.com/?search=A2HS ); - Bookmarks ( developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks ); ==КЭШИРОВАНИЕ ДАННЫХ (ОФФЛАЙН РЕЖИМ)== - CacheStorage ( developer.mozilla.org/ru/docs/Web/API/CacheStorage, caniuse.com/?search=CacheStorage ); - AppCache ( developer.mozilla.org/ru/docs/Web/HTML/Using_the_application_cache caniuse.com/offline-apps ); - IndexedDB ( developer.mozilla.org/ru/docs/Web/API/IndexedDB_API caniuse.com/IndexedDB ); ==СИНХРОНИЗАЦИЯ ДАННЫХ== - SyncManager ( developer.mozilla.org/en-US/docs/Web/API/Background_Synchronization_API, caniuse.com/?search=SyncManager ); - Background Fetch ( developer.mozilla.org/en-US/docs/Web/API/Background_Fetch_API, caniuse.com/?search=BackgroundFetch ); ==УВЕДОМЛЕНИЯ (СООБЩЕНИЯ)== - Notifications ( developer.mozilla.org/ru/docs/Web/API/Notifications_API, caniuse.com/?search=notification ); - Push ( developer.mozilla.org/ru/docs/Web/API/Push_API, caniuse.com/?search=Push ); В данный момент модуль позволяет: - настраивать manifest (иконки, обложка сайта, цвет вкладки браузера или рамки приложения, режим отображения сайта при запуске приложения и др.); - создавать иконку (ссылку) сайта на рабочем столе устройства (запуск сайта, как приложение) т.к. эта возможность работает для новых версий браузера, то для старых как альтернатива будет сообщение о добавлении сайта в закладки, для iOS также отдельное сообщение для ручной установки иконки на экран; - работать в оффлайн режиме ("CacheStorage"), чтобы пользователь с плохим интернетом мог читать информацию; - работать в оффлайн режиме ("AppCache"), чтобы пользователь с плохим интернетом мог читать информацию (в разработке); - работать в оффлайн режиме ("IndexedDB"), чтобы пользователь с плохим интернетом мог читать информацию (в разработке); - отправка запросов при появлении интернета "SyncManager" - синхронизация данных (в разработке); - присылать "Notifications" уведомления - при первом посещении страницы будет показано 1 раз новинки, а напоминания 1 раз в 10 минут, если пользователь не закрыл страницу сайта и в это время что-то новое появилось, тогда оно будет показано ему; - присылать "Push" уведомления тоже самое, что и Notifications, только может работать при закрытом браузере и на мобильных устройств (в режиме тестирования - пишите в лс); - публикация в магазинах приложений (в разработке - пишите в лс для содействия); Другие возможности дорабатываются со временем или подзаказ. Я не гарантирую, но должно работать в браузерах: ServiceWorker API Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 17+; Chrome - 40+; Firefox - 78+; Opera - 27+; Яндекс.Браузер - 15.2+; Safari - 11.1+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - 40+; Chrome для Android - 40+; Firefox для Android - 44+; Opera для Android - 27+; Samsung Internet - 4+; Safari для iOS - 11.3+; KaiOS (Firefox OS v2.6) - неизвестно; MANIFEST Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 17+; Chrome - 40+; Firefox - 44+; Opera - 26+; Яндекс.Браузер - 15.2+; Safari - 11.1+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - 46+; Chrome для Android - 46+; Firefox для Android - 46+; Opera для Android - 26+; Samsung Internet - 4.1+; Safari для iOS - 11.3+; KaiOS (Firefox OS v2.6) - 1.0; A2HS (создание иконки сайта на рабочем столе) Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 79+; Chrome - 40+; Firefox - 86+ (Поддержка за флагом); Opera - 80+ (Поддержка за флагом); Яндекс.Браузер - 15.6+; Safari - 11.3+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - 81+; Chrome для Android - 43+; Firefox для Android - 83+; Opera для Android - 64+; Samsung Internet - 4.1+; Safari для iOS - 11.3+; KaiOS (Firefox OS v2.6) - нет поддержки; Bookmarks (добавление сайта в закладки) Десктопные браузеры: Internet Explorer - нет поддержки, но есть аналог; Edge - 79+; Chrome - есть поддержка; Firefox - 45+; Opera - есть поддержка; Яндекс.Браузер - есть поддержка; Safari - нет поддержки; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - нет поддержки; Chrome для Android - неизвестно; Firefox для Android - нет поддержки; Opera для Android - неизвестно; Samsung Internet - неизвестно; Safari для iOS - нет поддержки; KaiOS (Firefox OS v2.6) - неизвестно; CacheStorage (оффлайн режим) Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 18+; Chrome - 43+; Firefox - 44+; Opera - 30; Яндекс.Браузер - 15.2+; Safari - 11.1+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - 43+; Chrome для Android - 43+; Firefox для Android - 44+; Opera для Android - 30+; Samsung Internet - 4.1+; Safari для iOS - 11.3+; KaiOS (Firefox OS v2.6) - неизвестно; AppCache (оффлайн режим) Десктопные браузеры: Internet Explorer - 10+; Edge - 12-84; Chrome - 4-84; Firefox - 4-83; Opera - 12-72; Яндекс.Браузер - 1.0-18.11; Safari - 4+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - 43+; Chrome для Android - 43+; Firefox для Android - 44+; Opera для Android - нет поддержки; Samsung Internet - 4.1+; Safari для iOS - 4+; KaiOS (Firefox OS v2.6) - 2.5+; IndexedDB (оффлайн режим и синхронизация данных) Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 12+; Chrome - 24+; Firefox - 16+; Opera - 15+; Яндекс.Браузер - 1.7+; Safari - 10+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - 37+; Chrome для Android - 25+; Firefox для Android - 22+; Opera для Android - 15+; Samsung Internet - 1.5+; Safari для iOS - 8+; KaiOS (Firefox OS v2.6) - 2.5; SyncManager (синхронизация данных) Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 79+; Chrome - 49+; Firefox - нет поддержки; Opera - 42; Яндекс.Браузер - 16.4+; Safari - нет поддержки; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - 49+; Chrome для Android - 49+; Firefox для Android - нет поддержки; Opera для Android - 62; Samsung Internet - 5+; Safari для iOS - нет поддержки; KaiOS (Firefox OS v2.6) - неизвестно; Background Fetch API (синхронизация данных) Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 79+; Chrome - 74+; Firefox - нет поддержки; Opera - 62; Яндекс.Браузер - неизвестно; Safari - нет поддержки; Vivaldi - неизвестно; Brave - неизвестно; Мобильные браузеры: Android webview - 49+; Chrome для Android - 74+; Firefox для Android - нет поддержки; Opera для Android - 53; Samsung Internet - 11+; Safari для iOS - нет поддержки; KaiOS (Firefox OS v2.6) - неизвестно; Notifications API (вывод уведомлений при открытом браузере) Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 14+; Chrome - 20+; Firefox - 4+; Opera - 23+; Яндекс.Браузер - 1.7+; Safari - 10+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - нет поддержки; Chrome для Android - 50+; Firefox для Android - 48+; Opera для Android - 42+; Samsung Internet - 4+; Safari для iOS - нет поддержки; KaiOS (Firefox OS v2.6) - 2.5; PUSH API (вывод сообщений при закрытом браузере) Десктопные браузеры: Internet Explorer - нет поддержки; Edge - 17+; Chrome - 50+; Firefox - 44+; Opera - 42+; Яндекс.Браузер - 16.6+; Safari - 14+; Vivaldi - 3.5+; Brave - 1.17+; Мобильные браузеры: Android webview - нет поддержки; Chrome для Android - 50+; Firefox для Android - 48+; Opera для Android - 42+; Samsung Internet - 5+; Safari для iOS - нет поддержки; KaiOS (Firefox OS v2.6) - 2.5; Комментарии автора: Safari v11.1+ (apple позволяет добавить иконку на рабочий только сделав 3 клика, push уведомления ещё недоступны) Safari для iOS v11.3+ (apple позволяет добавить иконку на рабочий только сделав 3 клика, push уведомления ещё недоступны для iphone, а вот для macOS есть возможность) Яндекс.Браузер API Табло (Не знаю имеет ли смысл добавлять, ответ разработчики Яндекс.Браузер не дают и документация удалена) KaiOS (Firefox OS v2.6) v1.0+ (с этой версии принимает иконки manifest ) (Нужно поддержать кнопочных - просьба писать в лс для помощи в тестировании) ВНИМАНИЕ! Оригинальные файлы магазина не заменяет! Рекомендую админ панель перевести на отдельный поддомен в целях безопасности и гарантии отсутствия ошибок из-за serviceWorker. serviceWorker будет иметь доступ к админке на короткое время (код отключения там устанавливается) т.к. адрес админки в поле видимости каталога, то есть serviceWorker работает со ссылками начиная с https://mysite.by/ или /. Модификатор "вносит изменения" в следующие файлы: УСЛОВИЯ СОГЛАШЕНИЯ - Beta версии устанавливаете на свой страх и риск - бэкап базы данных (далее - БД) обязателен; - Модуль (модификатор, дополнение, расширение, приложение) (далее - Модуль) можно устанавливать на 1 домен включая поддомены (одна покупка - один домен); - Редактировать код можно только под нужды своего магазина; - Распространение модуля запрещено; - Техническая поддержка (далее - ТП) осуществляется только при появлении ошибки, бага, глюка (зависания) и не совместимости модуля с заявленными версиями Opencart и шаблонов на момент продажи, при установке на боевой сайт (рабочий хостинг); - Адаптация модуля под другую версию Опенкарта и сторонние модули - платная; - Автор модуля оставляет за собой право в любое время внести изменение в настоящее условие, описание и исходный код модуля; - Автор модуля оставляет за собой право прекратить ТП пользователям по истечению 365 календарных дней со дня последнего обновления модуля (Full или Beta версии), или со дня окончания продления ТП, или при форс-мажорных обстоятельств; - Автор не несёт ответственности за потерю или находку дохода пользователя из-за работы модуля; - ТП осуществляется при условии соблюдения данного соглашения, пишите в личные сообщения. Автор buslikdrev долучення 02.12.20 Категорія Модули Системные требования php 5.4+, настроенный https протокол Метод активации Автоматическая активация Ioncube Loader Нет ocStore 3.0 2.3.0.2.4 2.3 2.2 2.1 OpenCart.Pro, ocShop Opencart.pro 2.3 Opencart.pro 2.1 OcShop 2.0.3.х Звернення до сервера розробника Нет Да -
Opencart - Android - JSON - получаем список товаров в приложении
ocdroid опубликовал запись в блоге в ocdroid blog
Всем привет! Сегодня мы разберем получение товаров из категории Opencart в Android-приложение через JSON. Для начала не будем использовать сторонние библиотеки, а сделаем все нативным образом, чтобы ознакомиться с базовыми принципами обмена данными. Итак, поехали Сперва нужно определить выдачу массива товаров в JSON-объект из магазина. Открываем catalog/controller/product/category.php И в цикле выдачи данных для товаров добавляем свои запросы. Перед $data['products'][] = array( Добавляем // изображение для списка, размер 100х100 if ($result['image']) { $json_image = $this->model_tool_image->resize($result['image'], 100, 100); } else { $json_image = $this->model_tool_image->resize('placeholder.png', 100, 100); } // создаем массив данных для каждого товара // получаем имя, путь изображения, описание и цену $data['json-products'][] = array( 'name' => $result['name'], 'thumb' => $json_image, 'description' => utf8_substr(trim(strip_tags(html_entity_decode($result['description'], ENT_QUOTES, 'UTF-8'))), 0, $this->config->get('theme_' . $this->config->get('config_theme') . '_product_description_length')) . '..', 'price' => $price, ); Дальше ищем response $this->response->setOutput($this->load->view('product/category', $data)); И заменяем на // формируем массив products $data['json_products'] = array( 'products' => $data['json-products'], ); // и отдаем его в json при запросе в адресной строке &json_products // для этого поставим условие запроса if (isset( $this->request->get['json_products'])) { $this->response->setOutput(json_encode($data['json_products'])); } else { $this->response->setOutput($this->load->view('product/category', $data)); } Таким образом, теперь при запросе к сайту по адресу мой-сайт/index.php?route=product/category&path=20&json_products мы будем получать массив данных вида: {"products":[ {"name":"Apple Cinema30'", "thumb":"http:\/\/store.url\/image\/cache\/catalog\/demo\/apple_cinema_30-100x100.jpg", "description":"The 30-inch Apple Cinema HD Display delivers an amazing 2560 x 1600 pixel resolution. Designed speci..", "price":"$100.00"}, {"name":"Canon EOS 5D", "thumb":"http:\/\/store.url\/image\/cache\/catalog\/demo\/canon_eos_5d_1-100x100.jpg", "description":"Canon's press material for the EOS 5D states that it 'defines (a) new D-SLR category', while we're n..", "price":"$100.00"}, . . . , . . . , ]} С серверной частью закончили, переходим к программной части приложения. Что мы будем делать? Получим JSON данные из url Разберем эти данные и актуализируем с listView(textView) Скачаем картинки, кешируем их в приложении и актуализируем по позициям в listView(imageView) Для начала не забудьте дать приложению разрешение на использование сети (в манифесте): <uses-permission android:name="android.permission.INTERNET"/> Также в папку res/drawable мы поместим заглушку для изображений(до того, как они спарсятся) blank.png (100x100px) Теперь разметка. Для простоты будем работать с activity_main и стандартным listView activity_main.xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/lv_products" android:layout_width="wrap_content" android:layout_height="wrap_content" tools:context=".MainActivity" /> </RelativeLayout> Здесь все просто - в релятивную разметку мы поместили listView c id=lv_products Теперь создадим кастомную разметку для этого listView lv_layout.xml: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/tv_product" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_marginTop="5dp" android:textColor="#195F74" android:textSize="20sp" android:textStyle="bold" /> <ImageView android:id="@+id/iv_thumb" android:layout_width="100dp" android:layout_height="100dp" android:layout_below="@id/tv_product" android:layout_centerVertical="true" android:contentDescription="@string/str_iv_thumb" android:padding="5dp" android:scaleType="fitXY" /> <TextView android:id="@+id/tv_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/tv_product" android:layout_toRightOf="@id/iv_thumb" android:textSize="16sp" /> <TextView android:id="@+id/tv_price" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/tv_description" android:layout_marginBottom="10dp" android:gravity="right" android:layout_marginRight="5dp" android:textColor="#cc3333" android:textSize="20sp" android:textStyle="bold"/> </RelativeLayout> С разметкой закончили — приступаем к коду Создаем файл ProductsJSONParser.java (это и будет класс парсера) package com.opencart.ocproducstlist; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.content.res.Resources; /** класс парсера JSON данных */ public class ProductsJSONParser { // Получаем JSONObject и возвращаем List public List<HashMap<String, Object>> parse(JSONObject jObject) { JSONArray jProducts = null; try { // Здесь элементы из массива 'products', который мы получаем из контроллера jProducts = jObject.getJSONArray("products"); } catch (JSONException e) { e.printStackTrace(); } // применяем getProducts к массиву объекта JSON // теперь каждый объект - это товар return getProducts(jProducts); } private List<HashMap<String, Object>> getProducts(JSONArray jProducts) { int productCount = jProducts.length(); List<HashMap<String, Object>> productList = new ArrayList<HashMap<String, Object>>(); HashMap<String, Object> product = null; // разбираем товары по одному и добавляем к объекту List for (int i = 0; i < productCount; i++) { try { // вызываем getProduct и парсим, добавляем product = getProduct((JSONObject) jProducts.get(i)); productList.add(product); } catch (JSONException e) { e.printStackTrace(); } } return productList; } // Разбираем JSON-объект product private HashMap<String, Object> getProduct(JSONObject jProduct) { HashMap<String, Object> product = new HashMap<String, Object>(); String name = ""; String thumb = ""; String description = ""; String price = ""; try { // обратите внимание на метод .replaceAll // без него разные "непечатные" символы будут отображаться неправильно name = jProduct.getString("name").replaceAll(""", "\""); thumb = jProduct.getString("thumb"); description = jProduct.getString("description").replaceAll(""", "\"").replaceAll("’", "\'"); price = jProduct.getString("price"); product.put("product", name); // здесь сперва ставим заглушку product.put("thumb", R.drawable.blank); product.put("thumb_path", thumb); product.put("description", description); product.put("price", price); } catch (JSONException e) { e.printStackTrace(); } return product; } } Ну а теперь MainActivity package com.opencart.ocproducstlist; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashMap; import java.util.List; import org.json.JSONObject; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.widget.ListView; import android.widget.SimpleAdapter; public class MainActivity extends Activity { ListView mListView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // URL с нашими JSON-данными String strUrl = "http://мойсайт.com/index.php?route=product/category&path=20&json_products"; // определяем задачу по загрузке // и запускаем ее с нашим url DownloadTask downloadTask = new DownloadTask(); downloadTask.execute(strUrl); // ссылаемся на ListView в activity_main mListView = (ListView) findViewById(R.id.lv_products); } /** метод загрузки данных из url */ private String downloadUrl(String strUrl) throws IOException { String data = ""; InputStream iStream = null; try { URL url = new URL(strUrl); // Создаем http соединение, соединяемся и считываем данные HttpURLConnection urlConnection = (HttpURLConnection) url .openConnection(); urlConnection.connect(); iStream = urlConnection.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader( iStream)); StringBuffer sb = new StringBuffer(); String line = ""; while ((line = br.readLine()) != null) { sb.append(line); } data = sb.toString(); br.close(); } catch (Exception e) { Log.d("Exception while downloading url", e.toString()); } finally { iStream.close(); } return data; } /** Асинхронно скачиваем json */ private class DownloadTask extends AsyncTask<String, Integer, String> { String data = null; @Override protected String doInBackground(String... url) { try { data = downloadUrl(url[0]); } catch (Exception e) { Log.d("Background Task", e.toString()); } return data; } @Override protected void onPostExecute(String result) { // закончили в non-ui ListViewLoaderTask listViewLoaderTask = new ListViewLoaderTask(); // начинаем парсить listViewLoaderTask.execute(result); } } /** Асинхронно парсим данные и кидаем в listView */ private class ListViewLoaderTask extends AsyncTask<String, Void, SimpleAdapter> { JSONObject jObject; // парсим в non-ui @Override protected SimpleAdapter doInBackground(String... strJson) { try { jObject = new JSONObject(strJson[0]); ProductsJSONParser productsJsonParser = new ProductsJSONParser(); productsJsonParser.parse(jObject); } catch (Exception e) { Log.d("JSON Exception1", e.toString()); } // Инстанцируем класс парсера ProductsJSONParser productsJsonParser = new ProductsJSONParser(); // Список для сохранения List<HashMap<String, Object>> products = null; try { // Получаем спарсеные данные в List (наш список) products = productsJsonParser.parse(jObject); } catch (Exception e) { Log.d("Exception", e.toString()); } // Ключи, которые используем в hashMap String[] from = { "product", "thumb", "description", "price" }; // и айдишники, используемые в listView int[] to = { R.id.tv_product, R.id.iv_thumb, R.id.tv_description, R.id.tv_price }; // задаем адаптер // и закидываем ключи в айдишники SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), products, R.layout.lv_layout, from, to); return adapter; } /** doInBackground выполнен - займемся картинками */ @Override protected void onPostExecute(SimpleAdapter adapter) { // Задаем адаптер для listview mListView.setAdapter(adapter); for (int i = 0; i < adapter.getCount(); i++) { HashMap<String, Object> hm = (HashMap<String, Object>) adapter .getItem(i); String imgUrl = (String) hm.get("thumb_path"); ImageLoaderTask imageLoaderTask = new ImageLoaderTask(); HashMap<String, Object> hmDownload = new HashMap<String, Object>(); hm.put("thumb_path", imgUrl); hm.put("position", i); // запускаем ImageLoaderTask для скачивания // и актуализации картинок в listview imageLoaderTask.execute(hm); } } } /** Асинхронно качаем картинки и помещаем в listView */ private class ImageLoaderTask extends AsyncTask<HashMap<String, Object>, Void, HashMap<String, Object>> { @Override protected HashMap<String, Object> doInBackground( HashMap<String, Object>... hm) { InputStream iStream = null; String imgUrl = (String) hm[0].get("thumb_path"); int position = (Integer) hm[0].get("position"); URL url; try { url = new URL(imgUrl); // создаем соединение и подключаемся HttpURLConnection urlConnection = (HttpURLConnection) url .openConnection(); urlConnection.connect(); // считываем данные iStream = urlConnection.getInputStream(); // директория кеширования File cacheDirectory = getBaseContext().getCacheDir(); // временно сохраняем картинку в кеш-дир File tmpFile = new File(cacheDirectory.getPath() + "/ocpl_" + position + ".png"); // поток в кеш-файл FileOutputStream fOutStream = new FileOutputStream(tmpFile); // из потока в картинку Bitmap b = BitmapFactory.decodeStream(iStream); // пишем файл в темп (png) b.compress(Bitmap.CompressFormat.PNG, 100, fOutStream); // сбрасываем и закрываем поток fOutStream.flush(); fOutStream.close(); // создаем hashMap для передачи картинки // в listview, в соответствии с позицией HashMap<String, Object> hmBitmap = new HashMap<String, Object>(); // сохраняем путь к картинке // и позицию картинки в listview hmBitmap.put("thumb", tmpFile.getPath()); hmBitmap.put("position", position); // возвращаем объект с картинкой и позицией return hmBitmap; } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(HashMap<String, Object> result) { // теперь получаем путь и позицию String path = (String) result.get("thumb"); int position = (Integer) result.get("position"); // задаем адаптер SimpleAdapter adapter = (SimpleAdapter) mListView.getAdapter(); // забираем объекты из hashMap // с соответствующей позицией в listview HashMap<String, Object> hm = (HashMap<String, Object>) adapter .getItem(position); // заменяем текущий путь (сейчас "заглушка" - res/drawable/blank.png) hm.put("thumb", path); // и сообщаем listView об изенении содержимого adapter.notifyDataSetChanged(); } } } Запускаем приложение и любуемся результатом: До новых встреч