|
Android Разработка игр на платформе Android |
02.11.2013, 14:02
|
#1
|
ПроЭктировщик
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений (для 271 пользователей)
|
загрузка картинки из архива сразу в Drawable
вопрос возник как всегда на ровном месте. понадобилось прочесть из zip-архива, что входит в apk (т.е. в проекте лежит в папке assets), файл. не распаковывать весь архив или файлы на диск/флешку (вдруг там места нет), а именно прочитать файл в поток и сразу закинуть его в Drawable для использования как фона кнопки, обоев и пр. (впрочем, там будут и файлы других форматов)
вот пример того, как я рылся в архивах до этого печального момента:
/* zipfilename - имя файла архива, filename - файл, который нужно найти в архиве * * unzipfilename - имя (и путь) файла, в который будет распакован файл filename */ public static void zipExtract(String zipfilename, String filename, String unzipfilename) { try { // буфер для чтения из архива byte[] buf = new byte[1024]; // поток архива ZipInputStream zipinputstream = null; // вхождения в архив ZipEntry zipentry; // создаем поток архива, параметр - свежесозданный поток файла архива zipinputstream = new ZipInputStream( new FileInputStream(zipfilename)); // получаем очередное вхождение в архив zipentry = zipinputstream.getNextEntry(); // пока все вхождения в архив не кончатся while (zipentry != null) { // получаем имя вхождения (запакованного файла или папки) String entryName = zipentry.getName(); if (entryName == filename) { // количество фактически прочитанных байтов int n; // поток для записи распакованного файла/папки FileOutputStream fileoutputstream; // открываем файл вхождения (файла/папки) File newFile = new File(entryName); // если очередное вхождение - папка, то пропускаем текущую итерацию цикла String directory = newFile.getParent(); if(directory == null) { if(newFile.isDirectory()) break; } // если вхождение - файл, то создаем выходной поток для записи распакованного файла fileoutputstream = new FileOutputStream(filename); // переписываем весь файл из архива в созданный поток while ((n = zipinputstream.read(buf, 0, 1024)) > -1) fileoutputstream.write(buf, 0, n); // закрываем поток fileoutputstream.close(); // закрываем вхождение zipinputstream.closeEntry(); // получаем следующее вхождение zipentry = zipinputstream.getNextEntry(); } } // закрываем поток архива zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } }
самому странно, что такую простую, вроде бы, вещь как извлечение файла из архива сразу в картинку не удается реализовать без необходимости распаковывать данные сначала в файлы(((
говорю сразу - мануалами уже обчитался. какаю кодом, блюю газетой. так что просьба ответить тем, у кого есть идеи по теме, а не советы типа "кури мануалы".
заранее благодарен.
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
Последний раз редактировалось barsunduk, 02.11.2013 в 22:15.
|
(Offline)
|
|
03.11.2013, 14:22
|
#2
|
ПроЭктировщик
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений (для 271 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
с текстовым файлом проще, конечно.
а вот что с картинками и музыкой делать прямо не знаю. ((( как bytearray превратить в картинку типа png (с alpha) или jpg?
/* zipfilename - имя файла архива, filename - файл, который нужно найти в архиве * * на выходе - массив байтов, содержащая извлеченный файл */ public static byte[] zipExtract(String zipfilename, String filename) { // буфер для строки byte[] buf = null; try { // поток архива ZipInputStream zipinputstream = null; // вхождения в архив ZipEntry zipentry; // создаем поток архива, параметр - свежесозданный поток файла архива zipinputstream = new ZipInputStream(new FileInputStream(zipfilename)); // получаем очередное вхождение в архив zipentry = zipinputstream.getNextEntry(); // пока все вхождения в архив не кончатся while (zipentry != null) { // получаем имя вхождения (запакованного файла или папки) String entryName = zipentry.getName(); // если это искомый файл if (entryName == filename) { // получаем размер найденного файла int entrysize = (int)zipentry.getSize(); // создаем буфер для чтения из архива buf = new byte[entrysize]; // читаем найденный файл из архива в буфер zipinputstream.read(buf, 0, entrysize); // закрываем вхождение zipinputstream.closeEntry(); // заканчиваем поиск break; } // получаем очередное вхождение в архив zipentry = zipinputstream.getNextEntry(); } // закрываем поток архива zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } // возвращаем буфер return buf; } /* zipfilename - имя файла архива, filename - файл, который нужно найти в архиве * * на выходе - строка, содержащая извлеченный файл */ public static String zipExtractTextfile(String zipfilename, String filename) { return zipExtract(zipfilename, filename).toString(); }
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
|
(Offline)
|
|
03.11.2013, 23:49
|
#3
|
Разработчик
Регистрация: 06.04.2008
Сообщений: 541
Написано 196 полезных сообщений (для 638 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
Есть замечательный класс BitmapFactory
В нем есть методы для получения Bitmap и из массива, и из файла, и даже из InputStream.
Из Bitmap легким движением руки получаем Drawable:
Drawable drawable = new BitmapDrawable(context.getResources(), bitmap);
Кстати, в случае InputStream не обязательно даже вспоминать про BitmapFactory, есть конструктор BitmapDrawable, принимающий в себя InputStream.
Читаешь файлы из zip-архива на первый взгляд правильно. Только вторую твою функцию можно будет уменьшить, учитывая, что не обязательно считывать картинку в массив байтов, а достаточно использовать InputStream.
А вообще, по поводу использования zip-архивов в качестве ассетов - я бы посоветовал перестать наркоманить и больше так не делать. Ты не забыл, что apk-файл - это тоже zip-архив?
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
04.11.2013, 13:14
|
#4
|
ПроЭктировщик
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений (для 271 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
Сообщение от Romanzes
Ты не забыл, что apk-файл - это тоже zip-архив?
|
просто где-то когда-то читал, что папка assets не сжимается, в ней всё остается как есть. отложилось в голове, хотя чушь явная.
но это не основная причина. просто хотел редактор и интерпретатор собрать - подсовываешь программе один архив, а внутри и контент и интерфейс...
а вариант с InputStream и BitmapDrawable я уже пробовал, он не пошел. видимо, там был мой косяк. вернусь к нему и буду искать дыры. спасибо!
до смешного дошло. вот этот изврат (нерабочий, ессно):
public Drawable zipExtractImage(String zipfilename, String filename) { Drawable img = null; try { ZipInputStream zipinputstream = new ZipInputStream(this.getAssets().open(zipfilename)); ZipEntry zipentry = zipinputstream.getNextEntry(); while (zipentry != null) { String entryName = zipentry.getName(); if (entryName == filename) { img = Drawable.createFromStream(zipinputstream, null); break; } zipentry = zipinputstream.getNextEntry(); } zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } return img; }
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
Последний раз редактировалось barsunduk, 08.11.2013 в 21:58.
|
(Offline)
|
|
15.11.2013, 01:41
|
#5
|
ПроЭктировщик
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений (для 271 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
...
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
|
(Offline)
|
|
15.11.2013, 01:57
|
#6
|
Разработчик
Регистрация: 06.04.2008
Сообщений: 541
Написано 196 полезных сообщений (для 638 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
Передай свой ZipInputStream в функцию BitmapFactory.decodeStream(InputStream is). Если ты в данный момент находишься на нужной тебе ZipEntry (ты переключаешься между ними с помощью getNextEntry()), то этот ZipInputStream выдаст только твою картинку, а не весь файл.
|
(Offline)
|
|
15.11.2013, 03:05
|
#7
|
ПроЭктировщик
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений (для 271 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
я это уже пытался делать. только сейчас понял, почему не работало. с контекстами напутано было.
короче, вот РАБОЧИЙ ВАРИАНТ:
package ru.tururu.turu;
import java.io.*; import java.util.zip.*;
import android.content.Context; import android.graphics.drawable.Drawable;
public class Unzip {
// тут другие функции будут // ...
/* Чтение картинки из архива в Assets. Пример вызова из Activity: * imageview1.setImageDrawable(Unzip.zipAssetsDrawable( * "image1.jpg", getApplicationContext())); * в папке Assets открывается архив assets.zip и из него извлекается * картинка filename сразу в Drawable */ public static Drawable zipAssetsDrawable(String filename, Context context) { Drawable d = null; String zipfilename = "assets.zip"; try { InputStream is = context.getAssets().open(zipfilename); ZipInputStream zipinputstream = new ZipInputStream(is); ZipEntry zipentry = zipinputstream.getNextEntry(); while (zipentry != null) { String entryName = zipentry.getName(); if (entryName.equalsIgnoreCase(filename)) { d = Drawable.createFromStream(zipinputstream, entryName); zipinputstream.closeEntry(); } zipentry = zipinputstream.getNextEntry(); } zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } return d; }
/* чтение картинки из архива на диске * в zipfilename - путь и имя архива, в filename - имя искомого файла * пример вызова из Assets: * imageview1.setImageDrawable(Unzip.zipFileDrawable( * "/mnt/sdcard/Android/data/TestProject/archive.zip", "image1.jpg"); */ public static Drawable zipFileDrawable(String zipfilename, String filename) { Drawable d = null; try { FileInputStream is = new FileInputStream(zipfilename); ZipInputStream zipinputstream = new ZipInputStream(is); ZipEntry zipentry = zipinputstream.getNextEntry(); while (zipentry != null) { String entryName = zipentry.getName(); if (entryName.equalsIgnoreCase(filename)) { d = Drawable.createFromStream(zipinputstream, entryName); zipinputstream.closeEntry(); } zipentry = zipinputstream.getNextEntry(); } zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } return d; } }
всё, теперь можно делать редактор ресурсов под виндой, а результат сохранять в виде архива, который закидывается в ассетс или на флешку
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
Последний раз редактировалось barsunduk, 15.11.2013 в 15:31.
|
(Offline)
|
|
15.11.2013, 13:29
|
#8
|
ПроЭктировщик
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений (для 271 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
назначение класса - доставать ресурсы напрямую из архива, который лежит в папке assets приложения, либо где-то на устройстве или флешке. ресурсы ( пока только графика и строки в UTF-8 ) помещаются сразу в контейнеры. собственно, как это сделать, я и хотел спросить, когда создавал тему.
package ru.turururu.turu; import java.io.*; import java.util.zip.*; import android.content.Context; import android.graphics.drawable.Drawable; public class Unzip { // у меня всегда в ассетс будет только 1 архив с данными, из которого нужно доставать ресурсы public static String zipfilename = "data.zip"; public static String StreamToString(InputStream is) { try { return new java.util.Scanner(is).useDelimiter("\\A").next(); } catch (java.util.NoSuchElementException e) { return ""; } } /* чтение строки из архива в Assets * пример вызова из Activity: * textview1.setText(Unzip.zipAssetsDrawable("text1.txt", getApplicationContext()));*/ public static String zipAssString(String filename, Context context) { String s = ""; try { ZipInputStream zipinputstream = new ZipInputStream(context.getAssets().open(zipfilename)); ZipEntry zipentry = zipinputstream.getNextEntry(); while (zipentry != null) { if (filename.equalsIgnoreCase(zipentry.getName())) { s = StreamToString(zipinputstream); zipinputstream.closeEntry(); } zipentry = zipinputstream.getNextEntry(); } zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } return s; } /* чтение строки из архива на диске * пример вызова из Activity: * textview1.setText(Unzip.zipFileString("/mnt/sdcard/Android/data/TestProject/archive.zip", "text1.txt"));*/ public static String zipFileString(String zipfilename, String filename) { String s = ""; try { FileInputStream is = new FileInputStream(zipfilename); ZipInputStream zipinputstream = new ZipInputStream(is); ZipEntry zipentry = zipinputstream.getNextEntry(); while (zipentry != null) { if (filename.equalsIgnoreCase(zipentry.getName())) { s = StreamToString(zipinputstream); zipinputstream.closeEntry(); } zipentry = zipinputstream.getNextEntry(); } zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } return s; } /* Чтение картинки из архива в Assets. Пример вызова из Activity: * imageview1.setImageDrawable(Unzip.zipAssetsDrawable("image1.jpg", getApplicationContext())); * в папке Assets открывается архив assets.zip и из него извлекается * картинка filename сразу в Drawable */ public static Drawable zipAssDrawable(String filename, Context context) { Drawable d = null; try { InputStream is = context.getAssets().open(zipfilename); ZipInputStream zipinputstream = new ZipInputStream(is); ZipEntry zipentry = zipinputstream.getNextEntry(); while (zipentry != null) { String entryName = zipentry.getName(); if (entryName.equalsIgnoreCase(filename)) { d = Drawable.createFromStream(zipinputstream, entryName); zipinputstream.closeEntry(); } zipentry = zipinputstream.getNextEntry(); } zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } return d; } /* чтение картинки из архива на диске * в zipfilename - путь и имя архива, * в filename - имя искомого файла * пример вызова из Assets: * imageview1.setImageDrawable(Unzip.zipFileDrawable("/mnt/sdcard/Android/data/TestProject/archive.zip", "image1.jpg"); */ public static Drawable zipFileDrawable(String zipfilename, String filename) { Drawable d = null; try { FileInputStream is = new FileInputStream(zipfilename); ZipInputStream zipinputstream = new ZipInputStream(is); ZipEntry zipentry = zipinputstream.getNextEntry(); while (zipentry != null) { String entryName = zipentry.getName(); if (entryName.equalsIgnoreCase(filename)) { d = Drawable.createFromStream(zipinputstream, entryName); zipinputstream.closeEntry(); } zipentry = zipinputstream.getNextEntry(); } zipinputstream.close(); } catch (Exception e) { e.printStackTrace(); } return d; } }
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
Последний раз редактировалось barsunduk, 15.11.2013 в 18:05.
|
(Offline)
|
|
15.11.2013, 20:51
|
#9
|
Разработчик
Регистрация: 06.04.2008
Сообщений: 541
Написано 196 полезных сообщений (для 638 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
По странному стечению обстоятельств, именно сегодня столкнулся с одной интересной технической тонкостью Андроида. Я работаю над SDK, которая автоматически встраивается в готовые Android-игры. Сегодня обнаружилось, что некоторые игры начинают падать в начале работы после перепаковки моей утилитой. Путем долгих расследований я обнаружил, что причина заключается в том, что звуки игры, хранящиеся в формате .ogg, в итоговом apk-файле оказываются в сжатом виде, в то время как в оригинальном архиве они лежали без компрессии. Поначалу я был удивлен, как это может каким-то образом влиять на что-либо. А затем нашел одну полезную статью, в которой рассказывается о том, что для многих типов ассетов любая компрессия нежелательна или даже смертельна. Самое интересное, что до версии андроида 2.3 вообще нельзя было хранить ассеты размером более 1 МБ в сжатом виде, иначе приложение падало. А у тебя вообще архив на архиве и архивом погоняет. Учти это в своем редакторе, а я не стал бы трогать это даже двенадцатиметровой палкой.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
16.11.2013, 21:45
|
#10
|
ПроЭктировщик
Регистрация: 09.05.2010
Адрес: рф ро шахты
Сообщений: 177
Написано 66 полезных сообщений (для 271 пользователей)
|
Ответ: загрузка картинки из архива сразу в Drawable
ок, выкидываем из ассетов архивы. там всё будет валяться в несжатом виде. архивы будут читаться только с устройства, если я когда-нибудь соберу редактор. спасибо за помощь и уместные страшилки!
*пошел выкидывать 12-метровую палку*
__________________
to be or not to be - it's not a question!
2b or not 2b = ff
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 20:52.
|