How to add an existing image? - java

I'm editing an open source app: A simple coloring page app for kids. I need to be able to make the user import his own images to be colored,a code for a button in my menu that when clicked by the user it opens his gallery(on SD) to choose an image from and then import this image to the view where he could color it . Here is the full source code.
And here is the code for loading images from R.drawable:
public class StartNewActivity extends NoTitleActivity implements View.OnClickListener
{
// This is an expensive operation.
public static int randomOutlineId()
{
return new ResourceLoader().randomOutlineId();
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Apparently this cannot be set from the style.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
setContentView(R.layout.start_new);
GridView gridview = (GridView) findViewById(R.id.start_new_grid);
gridview.setAdapter(new ImageAdapter(this));
}
public void onClick(View view)
{
setResult(view.getId());
finish();
}
private static class ResourceLoader
{
ResourceLoader()
{
// Use reflection to list resource ids of thumbnails and outline
// images.First, we list all the drawables starting with the proper
// prefixes into 2 maps.
Map<String, Integer> outlineMap = new TreeMap<String, Integer>();
Map<String, Integer> thumbMap = new TreeMap<String, Integer>();
Field[] drawables = R.drawable.class.getDeclaredFields();
for (int i = 0; i < drawables.length; i++)
{
String name = drawables[i].getName();
try
{
if (name.startsWith(PREFIX_OUTLINE))
{
outlineMap.put(name.substring(PREFIX_OUTLINE.length()),
drawables[i].getInt(null));
}
if (name.startsWith(PREFIX_THUMB))
{
thumbMap.put(name.substring(PREFIX_THUMB.length()),
drawables[i].getInt(null));
}
}
catch (IllegalAccessException e)
{
}
}
Set<String> keys = outlineMap.keySet();
keys.retainAll(thumbMap.keySet());
_outlineIds = new Integer[keys.size()];
_thumbIds = new Integer[keys.size()];
int j = 0;
Iterator<String> i = keys.iterator();
while (i.hasNext())
{
String key = i.next();
_outlineIds[j] = outlineMap.get(key);
_thumbIds[j] = thumbMap.get(key);
j++;
}
}
public Integer[] getThumbIds()
{
return _thumbIds;
}
public Integer[] getOutlineIds()
{
return _outlineIds;
}
public int randomOutlineId()
{
return _outlineIds[new Random().nextInt(_outlineIds.length)];
}
private static final String PREFIX_OUTLINE = "outline";
private static final String PREFIX_THUMB = "thumb";
private Integer[] _thumbIds;
private Integer[] _outlineIds;
}
private class ImageAdapter extends BaseAdapter
{
ImageAdapter(Context c)
{
_context = c;
_resourceLoader = new ResourceLoader();
}
public int getCount()
{
return _resourceLoader.getThumbIds().length;
}
public Object getItem(int i)
{
return null;
}
public long getItemId(int i)
{
return 0;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ImageView imageView;
if (convertView == null)
{
// If it's not recycled, initialize some attributes
imageView = new ImageView(_context);
imageView.setLayoutParams(new GridView.LayoutParams(145, 145));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(8, 8, 8, 8);
imageView.setOnClickListener(StartNewActivity.this);
}
else
{
imageView = (ImageView) convertView;
}
imageView.setImageResource(_resourceLoader.getThumbIds()[position]);
imageView.setId(_resourceLoader.getOutlineIds()[position]);
return imageView;
}
private Context _context;
private ResourceLoader _resourceLoader;
}
}

I think you need to use pictures from sd card in your application .
You can do so using the following links
Load images from sd card folder
loading images from SD card directory in GridView
How to Dynamically show images from a folder in sdcard
gridview and setImageBitmap when load image from SDcard
Hope it helps

Related

how display string array content through recycleview adapter

I have this structure of json api:
{
seasons: [
{
seasonstitle: "Season 1",
titles: "S1E1; S1E2; S1E3",
},
{
seasonstitle: "Season 2",
titles: "S2E1; S2E2; S2E3",
},
]
}
and I'm trying to display the values of these two keys: seasonstitle and titles but as you see the titles key has multiple values so I parsing the json like this:
ParsingClass:
public final class JsonDetailSeries {
public static ArrayList<SeriesItem> getSimpleMovieStringsFromJson(Context context, String moviesJsonString)
throws JSONException {
final String SEASONS = "seasons";
final String SEASONTITLE = "seasonstitle";
final String TITLES = "titles";
ArrayList<SeriesItem> parsedMovieData = new ArrayList<>();
JSONObject moviesObject = new JSONObject(moviesJsonString);
JSONArray moviesArray = moviesObject.getJSONArray(SEASONS);
for (int i = 0; i < moviesArray.length(); i++) {
String seasontitle;
String titles;
moviesObject = moviesArray.getJSONObject(i);
seasontitle = moviesObject.getString(SEASONTITLE);
titles = moviesObject.getString(TITLES);
String[] titlesArrray = titles.split(Pattern.quote(";"));
for (int j=0; j<titlesArrray.length; j++) {
Log.i("titles ", "=" + titlesArrray[j]);
}
parsedMovieData.add(new SeriesItem(seasontitle, titlesArrray));
}
return parsedMovieData;
}
}
when I saw it in log cat it splits correctly like this:
titles = S1E1
titles = S1E2
titles = S1E3
and so on, in my custom arraylist class which I return the data for it:
public class SeriesItem implements Parcelable {
private String seasontitle;
private String[] titlesArrray;
public SeriesItem(String seasontitle, String[] titlesArrray) {
this.seasontitle = seasontitle;
this.titlesArrray = titlesArrray;
}
#Override
public void writeToParcel(Parcel out, int flags) {
out.writeString(seasontitle);
out.writeStringArray(titlesArrray);
}
private SeriesItem(Parcel in) {
this.seasontitle = in.readString();
this.titlesArrray = in.createStringArray();
}
public SeriesItem() {
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<SeriesItem> CREATOR = new Creator<SeriesItem>() {
#Override
public SeriesItem createFromParcel(Parcel in) {
return new SeriesItem(in);
}
#Override
public SeriesItem[] newArray(int i) {
return new SeriesItem[i];
}
};
public String getSeasontitle() {
return seasontitle;
}
public String[] gettitlesArrray() {
return titlesArrray;
}
}
when I debug this class the data of titlesArrray recevied well each title split from the other one
so I'm trying to display this data in recyleview like this way:
Season1
S1E1
S1E2
S1E3
Season2
S2E1
S2E2
S2E3
so this is my adapter of recycleview:
public class SeriesAdapter extends RecyclerView.Adapter<SeriesAdapter.RecyclerViewHolder> {
ArrayList<SeriesItem> mMoviesItems;
private Context context;
private final SeriesAdapterOnClickHandler mClickHandler;
public interface SeriesAdapterOnClickHandler {
void onClick(SeriesItem movie);
}
public SeriesAdapter(SeriesAdapterOnClickHandler clickHandler) {
mClickHandler = clickHandler;
}
class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView seasontitle;
public final ListView titlesArray;
public RecyclerViewHolder(View view) {
super(view);
seasontitle = (TextView)itemView.findViewById(R.id.seasontitle);
titlesArray = (ListView) itemView.findViewById(R.id.titlesArray);
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int adapterPosition = getAdapterPosition();
SeriesItem movie = mMoviesItems.get(adapterPosition);
mClickHandler.onClick(movie);
}
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
context = viewGroup.getContext();
int layoutIdForListItem = R.layout.series_list_item;
LayoutInflater inflater = LayoutInflater.from(context);
boolean shouldAttachToParentImmediately = false;
View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
return new RecyclerViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
holder.seasontitle.setText(String.valueOf(mMoviesItems.get(position).getSeasontitle()));
holder.titlesArray.setText(String.valueOf(mMoviesItems.get(position).gettitlesArrray()));
}
#Override
public int getItemCount() {
if (null == mMoviesItems)
return 0;
else {
return mMoviesItems.size();
}
}
public void setMovieData(ArrayList<SeriesItem> movieData) {
mMoviesItems = movieData;
notifyDataSetChanged();
}
}
I tried to include a listview to display the titlesArray inside this recycleview and the problem is with this line:
holder.titlesArray.setText(String.valueOf(mMoviesItems.get(position).gettitlesArrray()));
I can't use setText for ListView so how can to display the titlesArray content inside this recycleview?
I tried to include a listview to display the titlesArray inside this recycleview
Do not do that.
What you want to do is handle two different types, the season and the episode. This question that will help you with that.
How to create RecyclerView with multiple view type?
Use Gson to parse Json instead of the native, it is much easier to implement.

Android: Show files in the storage with certain extentions in a listview

I'm creating an activity that shows files in the device (including external storage) with '.mp4' extension in a ListView.
Here's my Activity file
public class FindVideoActivity extends AppCompatActivity {
private List<String> fileNames;
private ListView lv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find_video);
fileNames = new ArrayList<>();
lv = (ListView) findViewById(R.id.find_video_list);
updateFileList();
}
public void updateFileList() {
String path;
String extension = Environment.getExternalStorageState();
if(extension.equals(Environment.MEDIA_MOUNTED)) {
path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/videostreaming/";
} else {
path = Environment.MEDIA_UNMOUNTED;
}
File file = new File(path);
ArrayAdapter<String> fileList = new ArrayAdapter<>(this, R.layout.file_list_item, fileNames);
VideoFinder finder = new VideoFinder();
File[] files = file.listFiles(finder);
for(File f: files) {
fileNames.add(f.getName());
}
lv.setAdapter(fileList);
}
}
In order to filter out the '.mp4' files, I created another class and named it VideoFinder.java. This class implements java.io.FilenameFilter. Here's the code.
public class VideoFinder implements FilenameFilter {
// overriding the method from the FilenameFilter interface.
#Override
public boolean accept(File dir, String filename) {
if(filename.endsWith(".mp4")) {
return true;
}
return false;
}
}
When I run the code above, it returns `NullPointerException` like the following.
Caused by: java.lang.NullPointerException
at com.marshall.videostreaming.FindVideoActivity.updateFileList(FindVideoActivity.java:46)
at com.marshall.videostreaming.FindVideoActivity.onCreate(FindVideoActivity.java:26)
So it says that the for loop in the updateFileList() method is catching the exception. I still cannot catch what I am missing in this code. Can anyone help?
Check your path, because assigning Environment.MEDIA_UNMOUNTED doesn't seem right. also check if Files is null, because this is why you got NPE.
Its my Main Java class
/**
* Created by ravindra on 2/12/15.
*/
public class GalleryScreen extends Activity implements View.OnClickListener{
private ArrayList<String> file_path = new ArrayList<String>();
GridView gridview;
ImageView left_iv;
TextView header_tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gallery_screen);
Bundle bundle = getIntent().getExtras();
gettingIds();
gettingOnClickListener();
fetchDeviceGallery();
}
private void fetchDeviceGallery() {
String[] projection = {MediaStore.Images.Thumbnails._ID};
// Create the cursor pointing to the SDCard
Cursor cursor = managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null, // Return all rows
null,
MediaStore.Images.Thumbnails.IMAGE_ID);
// Get the column index of the Thumbnails Image ID
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
file_path = getFilePaths();
GalleryAdapter adapter = new GalleryAdapter(GalleryScreen.this,file_path);
gridview.setAdapter(adapter);
System.out.println("Gallery images================="+cursor.getCount()+" "+columnIndex);
}
private void gettingIds() {
gridview = (GridView) findViewById(R.id.gridview);
left_iv = (ImageView) findViewById(R.id.left_iv);
header_tv = (TextView) findViewById(R.id.header_tv);
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
finish();
// overridePendingTransition(R.anim.left_to_right, R.anim.right_to_left);
}
});
}
private void gettingOnClickListener() {
left_iv.setOnClickListener(this);
}
public ArrayList<String> getFilePaths() {
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.ImageColumns.DATA};
Cursor c = null;
SortedSet<String> dirList = new TreeSet<String>();
ArrayList<String> resultIAV = new ArrayList<String>();
String[] directories = null;
if (u != null) {
c = GalleryScreen.this.managedQuery(u, projection, null, null, null);
}
if ((c != null) && (c.moveToFirst())) {
do {
String tempDir = c.getString(0);
tempDir = tempDir.substring(0, tempDir.lastIndexOf("/"));
try {
dirList.add(tempDir);
} catch (Exception e) {
}
}
while (c.moveToNext());
directories = new String[dirList.size()];
dirList.toArray(directories);
}
for (int i = 0; i < dirList.size(); i++) {
File imageDir = new File(directories[i]);
File[] imageList = imageDir.listFiles();
if (imageList == null)
continue;
for (File imagePath : imageList) {
try {
if (imagePath.isDirectory()) {
imageList = imagePath.listFiles();
}
if (imagePath.getName().contains(".jpg") || imagePath.getName().contains(".JPG")
|| imagePath.getName().contains(".jpeg") || imagePath.getName().contains(".JPEG")
|| imagePath.getName().contains(".png") || imagePath.getName().contains(".PNG")
|| imagePath.getName().contains(".mp4") || imagePath.getName().contains(".MP4")
||imagePath.getName().contains(".mp3") || imagePath.getName().contains(".MP3"))
{
System.out.println("RESOURCES ARE====="+imagePath);
String path = imagePath.getAbsolutePath();
resultIAV.add(path);
}
// }
catch (Exception e) {
e.printStackTrace();
}
}
}
return resultIAV;
}
#Override
public void onClick(View v) {
switch (v.getId())
{
case R.id.left_iv:
finish();
overridePendingTransition(R.anim.left_to_right, R.anim.right_to_left);
break;
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
overridePendingTransition(R.anim.left_to_right, R.anim.right_to_left);
}
}
And Its adapter class is as follow:-
/**
* Created by ravindra on 2/12/15.
*/
public class GalleryAdapter extends BaseAdapter {
private final DisplayImageOptions options;
private final ImageLoader imageLoader;
Activity activity;
ArrayList<String> arrayList = new ArrayList<String>();
public GalleryAdapter(Activity activity, ArrayList<String> arrayList) {
this.activity = activity;
this.arrayList = arrayList;
imageLoader = ImageLoader.getInstance();
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(activity));
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.loader)
.showImageForEmptyUri(R.drawable.loader)
.showImageOnFail(R.drawable.loader)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
public class ViewHolder {
ImageView gallery_item;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder _viewHolder;
if (convertView == null) {
_viewHolder = new ViewHolder();
LayoutInflater _layInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = _layInflater.inflate(R.layout.gallery_item, null);
_viewHolder.gallery_item = (ImageView) convertView.findViewById(R.id.gallery_item);
convertView.setTag(_viewHolder);
} else {
_viewHolder = (ViewHolder) convertView.getTag();
}
if (arrayList.get(position).contains(".mp3") || arrayList.get(position).contains(".MP3"))
{
_viewHolder.gallery_item.setImageResource(R.drawable.audio_img);
}
else {
imageLoader.displayImage("file://" + arrayList.get(position), _viewHolder.gallery_item, options, null);
}
return convertView;
}
}

OOM exception in ImageAdapter

LogCat is giving me this error:
Throwing OutOfMemoryError "Failed to allocate a 7485708 byte allocation with 2097152 free bytes and 5MB until OOM"
--- decoder->decode returned false
Shutting down VM
FATAL EXCEPTION: main
Process: de.holg.memory, PID: 2104
java.lang.OutOfMemoryError: Failed to allocate a 7485708 byte allocation with 2097152 free bytes and 5MB until OOM
I'm adding 6 pictures to an array but when I add "pic_1" 6 times no error occurs. The are all ~ 200kb. The pictures are displayed in my GridView after OnClick. Sometimes I can click 3 times... sometimes only once. On my phone I can click more often.
private Integer[] mThumbIds = {
R.drawable.pic_1,
R.drawable.pic_2,
R.drawable.pic_3,
R.drawable.pic_4,
R.drawable.pic_5,
R.drawable.pic_6,
};
My ImageAdapter Class:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private Integer[] pieces;
private List<ImageView> imageViewsList;
private int piece_up = -1;
public ImageAdapter(Context c) {
mContext = c;
List<Integer> ipieces = new ArrayList<Integer>();
for(int i=0; i<6; i++) {
ipieces.add(i);
ipieces.add(i);
}
Collections.shuffle(ipieces);
pieces = (Integer[]) ipieces.toArray(new Integer[0]);
createImageViews();
}
private void createImageViews() {
imageViewsList = new ArrayList<ImageView>();
for(int position = 0; position < getCount(); position++) {
ImageView imageView;
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(150, 150));
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setPadding(8, 8, 8, 8);
imageView.setImageResource(R.drawable.card_back);
imageViewsList.add(imageView);
installClick(position);
}
}
public int getCount() {
return 12; //mThumbIds.length;
}
public Object getItem(int position) {
return imageViewsList.get(position);
}
public long getItemId(int position) {
return pieces[position].longValue();
}
// create a new ImageView for each item referenced by the Adapter
public synchronized View getView(int position, View convertView, ViewGroup parent) {
return (ImageView) imageViewsList.get(position);
}
public void installClick(int position) {
// final int pos = position;
final ImageAdapter self = this;
Log.d("ImageAdapter", "click *" + Integer.toString(position));
ImageView imageView =(ImageView) imageViewsList.get(position);
imageView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int pos = imageViewsList.indexOf((ImageView) v);
Log.d("ImageAdapter", "click!" + Integer.toString(pos));
show(pos);
//UI update
if (piece_up == -1 || piece_up == pos) {
// first click
piece_up = pos;
} else {
// second click
if (pieces[pos] == pieces[piece_up]) {
// ok, it's equal
Toast.makeText(mContext, "good!", Toast.LENGTH_SHORT).show();
//
// remove click handler
removeClick(pos);
removeClick(piece_up);
} else {
//try again;
int aux[] = {piece_up, pos};
SleepHide update = new SleepHide(mContext, self, aux);
Handler mHandler = new Handler();
mHandler.postDelayed(update, 1500);
}
piece_up = -1;
}
}
});
}
public void removeClick(int position) {
ImageView aux;
aux = (ImageView) imageViewsList.get(position);
aux.setOnClickListener(null);
}
public void hide(int position) {
ImageView img;
img = (ImageView) imageViewsList.get(position);
//int piece = pieces[position];
img.setImageResource(R.drawable.card_back);
}
public void show(int position) {
ImageView img;
img = (ImageView) imageViewsList.get(position);
int piece = pieces[position];
img.setImageResource(mThumbIds[piece]);
}
//
// references to our images
private Integer[] mThumbIds = {
R.drawable.pic_1,
R.drawable.pic_2,
R.drawable.pic_3,
R.drawable.pic_4,
R.drawable.pic_5,
R.drawable.pic_6,
};
}
class SleepHide implements Runnable {
//private Context context;
private int[] positions;
private ImageAdapter adapter;
public SleepHide(Context c, ImageAdapter b, int[] pos) {
//context = c;
adapter = b;
positions = pos;
Log.d("SleepHide", "click!");
adapter.removeClick(pos[0]);
adapter.removeClick(pos[1]);
}
public void run() {
Log.d("SleepHide", "run!");
adapter.hide(positions[0]);
adapter.hide(positions[1]);
adapter.installClick(positions[0]);
adapter.installClick(positions[1]);
}
}
You can add this line to application class declaration into manifest file to request a larger heap size.
android:largeHeap="true"
application class declaration in AndroidManifest.xml
<application
android:label="#string/app_name"
android:allowBackup="true"
android:icon="#drawable/title_image"
android:largeHeap="true">
</application>
This will remove your OOM crashes completely!!
The app is going out of heap size.So you have to decode the image in such a way that it will fall under the heap size.Do this code in your adapter
You can change your show() method in adapter.
public void show(int position) {
ImageView img;
img = (ImageView) imageViewsList.get(position);
int piece = pieces[position];
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = false;
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inSampleSize = 3;
options.inPurgeable = true;
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
mThumbIds[piece],options);
img.setImageBitmap(icon);
}
Try once.

Loading images from JSON as you scroll in Android

I am creating an app with many products being loaded from a JSON file. Everything is working fine, but I have a small problem and I am having difficulty finding an answer to it. On a click of a button, I get all data from JSON file located on a server (it contains a URL value to get the picture of the product). When the button is clicked I would like to move to a list of products straight away and only load visible images. Instead it takes about 8 seconds to load and it loads all images before hand. Could somebody please tell me what am I doing wrong? I read online I should use something like so: imageLoader.DisplayImage(data[position], image);, but I am using a Hashmap, not just a string.
Here is my code, any help would be greatly appreciated:
LazyAdapter
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_row, null);
TextView brand = (TextView)vi.findViewById(R.id.brand); // title
TextView name = (TextView)vi.findViewById(R.id.name); // artist name
TextView price = (TextView)vi.findViewById(R.id.price); // duration
TextView imgValue = (TextView)vi.findViewById(R.id.imgValue);
//TextView rating = (TextView)vi.findViewById(R.id.rating); // rating
ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image
HashMap<String, String> products = new HashMap<String, String>();
products = data.get(position);
// Setting all values in listview
brand.setText(products.get(CustomizedListView.TAG_BRAND));
name.setText(products.get(CustomizedListView.TAG_NAME));
price.setText("£" + products.get(CustomizedListView.TAG_MIN_GBP));
imgValue.setText(products.get(CustomizedListView.TAG_IMG));
imgValue.setVisibility(View.GONE);
//rating.setText("Rating: " + song.get(CustomizedListView.TAG_RATING_NO) + "/5");
imageLoader.DisplayImage("http://debenhams.scene7.com/is/image/Debenhams/" + imgValue.getText() + "?hei=440&op_usm=1.1,0.5,0,0", thumb_image);
return vi;
}
}
ListView
public class CustomizedListView extends Activity {
// All static variables
static final String link = "https://dl.dropboxusercontent.com/u/142838353/productlist.json";
// XML node keys
static final String TAG_PRODUCTS = "Products";
static final String TAG_PRODNUM = "prodnum";
static final String TAG_BRAND = "brand";
static final String TAG_NAME = "name"; // parent node
static final String TAG_MIN_GBP = "minGBP";
static final String TAG_IMG = "img";
static final String TAG_RATING_NO = "rating_number";
JSONArray products = null;
ListView list;
LazyAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shop);
// Hashmap for ListView
ArrayList<HashMap<String, String>> productList = new ArrayList<HashMap<String, String>>();
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
JSONObject json = jParser.getJSONFromUrl(link);
try {
// Getting Array of Contacts
products = json.getJSONArray(TAG_PRODUCTS);
// looping through All Contacts
for(int i = 0; i < products.length(); i++){
JSONObject c = products.getJSONObject(i);
// Storing each json item in variable
// String prodnum = c.getString(TAG_PRODNUM);
String brand = c.getString(TAG_BRAND);
String name = c.getString(TAG_NAME);
String img = c.getString(TAG_IMG);
String price = c.getString(TAG_MIN_GBP);
//String ratingNo = c.getString(TAG_RATING_NO);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_MIN_GBP, price);
map.put(TAG_BRAND, brand);
map.put(TAG_NAME, name);
map.put(TAG_IMG, img);
//map.put(TAG_RATING_NO, ratingNo);
// adding HashList to ArrayList
productList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
list=(ListView)findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
adapter=new LazyAdapter(this, productList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String brand = ((TextView) view.findViewById(R.id.brand)).getText().toString();
String name = ((TextView) view.findViewById(R.id.name)).getText().toString();
String imgValue = ((TextView) view.findViewById(R.id.imgValue)).getText().toString();
String price = ((TextView) view.findViewById(R.id.price)).getText().toString();
//String imgVal = ((ImageView) view.findViewById(R.id.list_image)).;
//String imgVal = ((ImageView) view.findViewById(R.id.img)).getResources().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(), ProductActivity.class);
in.putExtra(TAG_BRAND, brand);
in.putExtra(TAG_NAME, name);
in.putExtra(TAG_IMG, imgValue);
in.putExtra(TAG_MIN_GBP, price);
startActivity(in);
}
});
}
#Override
public void onDestroy()
{
list.setAdapter(null);
super.onDestroy();
}
}
ImageLoader
public class ImageLoader {
MemoryCache memoryCache=new MemoryCache();
FileCache fileCache;
private Map<ImageView, String> imageViews=Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
ExecutorService executorService;
Handler handler=new Handler();//handler to display images in UI thread
public ImageLoader(Context context){
fileCache=new FileCache(context);
executorService=Executors.newFixedThreadPool(5);
}
final int stub_id=R.drawable.default_image;
public void DisplayImage(String url, ImageView imageView)
{
imageViews.put(imageView, url);
Bitmap bitmap=memoryCache.get(url);
if(bitmap!=null)
imageView.setImageBitmap(bitmap);
else
{
queuePhoto(url, imageView);
imageView.setImageResource(stub_id);
}
}
private void queuePhoto(String url, ImageView imageView)
{
PhotoToLoad p=new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
}
private Bitmap getBitmap(String url)
{
File f=fileCache.getFile(url);
//from SD cache
Bitmap b = decodeFile(f);
if(b!=null)
return b;
//from web
try {
Bitmap bitmap=null;
URL imageUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
conn.setConnectTimeout(30000);
conn.setReadTimeout(30000);
conn.setInstanceFollowRedirects(true);
InputStream is=conn.getInputStream();
OutputStream os = new FileOutputStream(f);
Utils.CopyStream(is, os);
os.close();
conn.disconnect();
bitmap = decodeFile(f);
return bitmap;
} catch (Throwable ex){
ex.printStackTrace();
if(ex instanceof OutOfMemoryError)
memoryCache.clear();
return null;
}
}
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,o);
stream1.close();
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=256;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
//Task for the queue
private class PhotoToLoad
{
public String url;
public ImageView imageView;
public PhotoToLoad(String u, ImageView i){
url=u;
imageView=i;
}
}
class PhotosLoader implements Runnable {
PhotoToLoad photoToLoad;
PhotosLoader(PhotoToLoad photoToLoad){
this.photoToLoad=photoToLoad;
}
#Override
public void run() {
try{
if(imageViewReused(photoToLoad))
return;
Bitmap bmp=getBitmap(photoToLoad.url);
memoryCache.put(photoToLoad.url, bmp);
if(imageViewReused(photoToLoad))
return;
BitmapDisplayer bd=new BitmapDisplayer(bmp, photoToLoad);
handler.post(bd);
}catch(Throwable th){
th.printStackTrace();
}
}
}
boolean imageViewReused(PhotoToLoad photoToLoad){
String tag=imageViews.get(photoToLoad.imageView);
if(tag==null || !tag.equals(photoToLoad.url))
return true;
return false;
}
//Used to display bitmap in the UI thread
class BitmapDisplayer implements Runnable
{
Bitmap bitmap;
PhotoToLoad photoToLoad;
public BitmapDisplayer(Bitmap b, PhotoToLoad p){bitmap=b;photoToLoad=p;}
public void run()
{
if(imageViewReused(photoToLoad))
return;
if(bitmap!=null)
photoToLoad.imageView.setImageBitmap(bitmap);
else
photoToLoad.imageView.setImageResource(stub_id);
}
}
public void clearCache() {
memoryCache.clear();
fileCache.clear();
}
}
If you're not averse to using a library to do it, I had a lot of success with Universal Image Loader. It takes a lot of the complexity of the problem away and is pretty easy to get set up. There's some discussion of the problem from a while back with a few other implementations (I'm not sure if any of them are maintained though). Even if you don't use the library, their design patterns might be a useful starting point.

How to make background thread for loading image in android ,gallery widget

I want to read images from URL and show it in android gallery widget.
so I wrote below code in onCreate() method .
list = GuideDAO.getAllImages(businessId);
Gallery g = (Gallery) findViewById(R.id.gallery);
g.setSpacing(2);
// Set the adapter to our custom adapter (below)
if(list.size() > 0)
{
g.setAdapter(new ImageAdapter(this,list));
}
This is my ImageAdapter
public class ImageAdapter extends BaseAdapter {
List<Images> glist = null;
private String url;
public ImageAdapter(Context c,List<Images> lst) {
mContext = c;
glist = lst;
int i=0;
for (Images id : glist) {
url = id.getImageURL(); // Getting URL
InputStream inStream = null;
if (url.startsWith("http")) {
url = url.replace(" ", "%20");
HttpURLConnection conn;
try {
conn = (HttpURLConnection)new URL(url).openConnection();
conn.setDoInput(true);
conn.connect();
inStream = conn.getInputStream();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
inStream = new FileInputStream(url);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inPurgeable = true;
Bitmap b = BitmapFactory.decodeStream(inStream, null, options);
mImageCollection[i]=b;
i++;
}
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView i = new ImageView(mContext);
i.setImageBitmap(mImageCollection[position]);
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(136, 88));
return i;
}
private Context mContext;
private String[] mImageURLs = {};
private Bitmap[] mImageCollection = {};
}
This throw error because it not in Thread. How can I change this code so that URL reading and image loads in background?
So I have changed my ImageAdapter by using SmartImageView , which handles background thread and caching.
public class ImageAdapter extends BaseAdapter {
List<ImageGallery> glist = null;
private String url;
public ImageAdapter(Context c,List<ImageGallery> lst) {
mContext = c;
glist = lst;
int i=0;
al = new ArrayList<String>();
for (ImageGallery id : glist) {
al.add(id.getImageURL());
}
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("deepak", "getview gallery");
SmartImageView i = new SmartImageView(mContext);
i.setImageUrl(al.get(position));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setLayoutParams(new Gallery.LayoutParams(136, 88));
return i;
}
private Context mContext;
private String[] mImageURLs = {};
private ArrayList<String> al;
private Bitmap[] mImageCollection = {};
private Integer[] mImageIds = {};
}
But my getView() is not getting called now.
you can make use of Smart Image view. SmartImageView is a drop-in replacement for Android’s standard ImageView which additionally allows images to be loaded from URLs or the user’s contact address book. Images are cached to memory and to disk for super fast loading.
Please refer the following link for more info https://github.com/loopj/android-smart-image-view .hope this may help u to accomplish ur task
I'd suggest writing an AsyncImageLoader class and having it handle image downloads from http. This way you can cache and manage everything on separate threads and have it set the image to the view once the loading is complete. Also you could use this class throughout the application if you want to download images elsewhere.
you could call something like mImageLoader.loadImage(myImageView, Url) in your adapter and it would drop it in once it was finished loading.
if you want more details let me know :)

Categories

Resources