Related
When using Custom Class show a pic on TextView,
I use spanned to show A NetImage on TextView, \
code like Below
Spanned spanned = Html.fromHtml(string, new NetImageGetter(mContext, holderNormal.tv_content),
new NetTagHandler(mContext));
holderNormal.tv_content.setText(spanned);
NetImageGetter like below:
public class NetImageGetter implements ImageGetter {
private Context context;
private TextView tv;
private int height;
public NetImageGetter(Context context, TextView tv) {
this.context = context;
this.tv = tv;
height = CommonUtil.dip2px(context, 18);
if (height == 0) {
height = 36;
}
}
#Override
public Drawable getDrawable(String source) {
// 将source进行MD5加密并保存至本地
String imageName = Common.md5(source);
String rootPath = QikeApplication.mCacheNeedClearDir; // 获取SDCARD的路径
// 获取图片后缀名
String[] ss = source.split("\\.");
String ext = ss[ss.length - 1];
// 最终图片保持的地址
String savePath = rootPath + "/" + imageName + "." + ext;
File file = new File(savePath);
if (file.exists()) {
// 如果文件已经存在,直接返回
Drawable drawable = Drawable.createFromPath(savePath);
if (drawable != null) {
int picHeight = drawable.getIntrinsicHeight();
int picWidth = drawable.getIntrinsicWidth();
drawable.setBounds(0, 0, ((int) (height / picHeight * picWidth)), height);
return drawable;
}
}
// 不存在文件时返回默认图片,并异步加载网络图片
Resources res = context.getResources();
URLDrawable drawable = new URLDrawable(res.getDrawable(R.drawable.icon));
new ImageAsync(drawable).execute(savePath, source);
return drawable;
}
private class ImageAsync extends AsyncTask<String, Integer, Drawable> {
private URLDrawable drawable;
public ImageAsync(URLDrawable drawable) {
this.drawable = drawable;
}
#Override
protected Drawable doInBackground(String... params) {
String savePath = params[0];
String url = params[1];
InputStream in = null;
try {
// 获取网络图片
HttpGet http = new HttpGet(url);
HttpClient client = new DefaultHttpClient();
HttpResponse response = (HttpResponse) client.execute(http);
BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(response.getEntity());
in = bufferedHttpEntity.getContent();
} catch (Exception e) {
e.printStackTrace();
try {
if (in != null)
in.close();
} catch (Exception e2) {
}
}
if (in == null)
return drawable;
try {
File file = new File(savePath);
String basePath = file.getParent();
File basePathFile = new File(basePath);
if (!basePathFile.exists()) {
basePathFile.mkdirs();
}
file.createNewFile();
FileOutputStream fileout = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len = 0;
while ((len = in.read(buffer)) != -1) {
fileout.write(buffer, 0, len);
}
fileout.flush();
Drawable mDrawable = Drawable.createFromPath(savePath);
return mDrawable;
} catch (Exception e) {
e.printStackTrace();
}
return drawable;
}
#Override
protected void onPostExecute(Drawable result) {
super.onPostExecute(result);
if (result != null) {
drawable.setDrawable(result);
tv.setText(tv.getText()); // 通过这里的重新设置 TextView 的文字来更新UI
}
}
}
public class URLDrawable extends BitmapDrawable {
private Drawable drawable;
public URLDrawable(Drawable defaultDraw) {
setDrawable(defaultDraw);
}
private void setDrawable(Drawable nDrawable) {
drawable = nDrawable;
int picHeight = drawable.getIntrinsicHeight();
int picWidth = drawable.getIntrinsicWidth();
if (picWidth != 0) {
drawable.setBounds(0, 0, ((int) (height / picHeight * picWidth)), height);
setBounds(0, 0, ((int) (height / picHeight * picWidth)), height);
}
}
#Override
public void draw(Canvas canvas) {
try {
drawable.draw(canvas);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
And use it on a adapter
run normal,but on some phone type, throw a StackOverflowError on
java.lang.StackOverflowError
at com.telecast.library.util.NetPicTextView.NetImageGetter$URLDrawable.draw(NetImageGetter.java:166)
I write a try catch,but useless.
Someone can help me?
I have used the async task to download the data and then showing those images in the list view I used the cache to store the images as they are repeating but not in an order. But the images gets jumbled up and sometimes they don't download. I tried searching this, but couldn't find that.
This was one of mine dream company question and i didn't clear because of this.
Please help me around.
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final String BASE_URL = "https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=android&start=";
private static final String IMAGE_JSON_KEY = "unescapedUrl";
private static final String RESULTS_JSON_KEY = "results";
private static final String RESPONSE_DATA_JSON_KEY = "responseData";
private int mCurrentPage;
private ListView mListView;
private Context mContext;
ArrayList<String> mImageUrls;
private LruCache<String, Bitmap> mCache;
private CustomListAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get memory class of this device, exceeding this amount will throw an
// OutOfMemory exception.
final int memClass = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = 1024 * 1024 * memClass / 8;
// Initialize variables
mContext = this;
mCache = new LruCache<String, Bitmap>(cacheSize) {
#Override
protected int sizeOf(String key, Bitmap value) {
// The cache size will be measured in bytes rather than number of items.
return value.getByteCount();
}
};
mListView = (ListView) findViewById(R.id.list_view);
mAdapter = new CustomListAdapter();
mImageUrls = new ArrayList<>();
// If the urls are wrong then
if (mImageUrls.isEmpty() || checkDiff()) {
fetchNewImageUrls();
}
// Set the adapter to the list view
mListView.setAdapter(mAdapter);
}
class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private String mUrl;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
#Override
protected Bitmap doInBackground(String... params) {
String imageUrl = params[0];
mUrl = imageUrl;
Bitmap bitmap = getBitmapFromMemCache(imageUrl);
if (bitmap == null) {
try {
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
// Closing the stream after getting the sample size
InputStream inputStream = connection.getInputStream();
byte[] imageByteArray = convertToByteArray(inputStream);
bitmap = decodeSampledBitmap(imageByteArray, 200, 200);
inputStream.close();
if (bitmap != null) {
Log.d(TAG, "Image downloaded: " + imageUrl);
addBitmapToMemoryCache(imageUrl, bitmap);
} else {
Log.d(TAG, "Null Bitmap downloaded for: " + imageUrl);
}
connection.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
Log.d(TAG, "Already present in the Cache");
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = (ImageView) imageViewReference.get();
if (imageView != null && imageView.getTag().equals(mUrl)) {
imageView.setImageBitmap(bitmap);
}
}
}
}
public class CustomListAdapter extends BaseAdapter {
#Override
public int getCount() {
return mImageUrls.size();
}
#Override
public Object getItem(int position) {
return mImageUrls.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d(TAG, "Get View is called for position: " + position);
View view = convertView;
Holder holder = null;
// Holder represents the elements of the view to use
// Here are initialized
if (view == null) {
view = LayoutInflater.from(mContext).inflate(R.layout.row_item, parent, false);
holder = new Holder();
holder.mRowImage = (ImageView) view.findViewById(R.id.image_view);
holder.mRowText = (TextView) view.findViewById(R.id.row_text);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
// Set default image background
holder.mRowImage.setImageResource(R.drawable.ic_launcher);
// here do operations in holder variable example
holder.mRowText.setText("Image Number: " + position);
// Set the tag for the imageview
holder.mRowImage.setTag(mImageUrls.get(position));
new BitmapWorkerTask(holder.mRowImage).execute(mImageUrls.get(position));
return view;
}
}
public static class Holder {
TextView mRowText;
ImageView mRowImage;
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mCache.put(key, bitmap);
}
}
public Bitmap getBitmapFromMemCache(String key) {
return (Bitmap) mCache.get(key);
}
public Bitmap decodeSampledBitmap(byte[] imageByteArray, int reqWidth, int reqHeight) {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length, options);
return bm;
}
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float) height / (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
Log.d(TAG, "Sample size is: " + inSampleSize);
return inSampleSize;
}
private void fetchNewImageUrls() {
new AsyncTask<String, Void, Boolean>() {
#Override
protected Boolean doInBackground(String... params) {
try {
StringBuilder response = new StringBuilder();
URL url = new URL(params[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
response.append(inputLine);
in.close();
connection.disconnect();
String resp = response.toString();
Log.d(TAG, "Response is: " + response);
// Parsing the response
JSONObject jsonObject = new JSONObject(resp);
JSONObject jsonObject1 = jsonObject.getJSONObject(RESPONSE_DATA_JSON_KEY);
JSONArray jsonArray = jsonObject1.getJSONArray(RESULTS_JSON_KEY);
for (int i = 0; i < 4; i++) {
JSONObject dataObject = jsonArray.getJSONObject(i);
mImageUrls.add(dataObject.getString(IMAGE_JSON_KEY));
}
mCurrentPage++;
Log.d(TAG, "Number of image urls are: " + mImageUrls.size());
return true;
} catch (JSONException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
#Override
protected void onPostExecute(Boolean value) {
super.onPostExecute(value);
if (checkDiff() && value) {
Log.d(TAG, "Again fetching the Images");
fetchNewImageUrls();
}
if (!value) {
Log.d(TAG, "Error while getting the response");
}
mAdapter.notifyDataSetChanged();
}
}.execute(BASE_URL + mCurrentPage);
}
private boolean checkDiff() {
int diff = mImageUrls.size() - mCurrentPage * 4;
Log.d(TAG, "Diff is: " + diff);
return diff < 8;
}
public static byte[] convertToByteArray(InputStream input) {
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
return output.toByteArray();
}
}
Since you do not cancel the unfinished "out of view" downloads these may interfere with your gui.
Example
listview line1 shows item#1 with has an async task to download image "a" not completed yet
scroll down, line1 is now invisible;
listview line8 becomes visible recycling item#1 new async task to download image "x"
async task to download image "a" finishes displaying wrong image. Line8 shows image "a" instead of "x"
to solve this you have to cancel the pending unnecessary unfinished async task-s
public static class Holder {
ImageView mRowImage;
String mImageUrl;
// neccessary to cancel unfinished download
BitmapWorkerTask mDownloader;
}
static class BitmapWorkerTask extends AsyncTask<Holder, Void, Bitmap> {
Holder mHolder;
protected Bitmap doInBackground(Holder... holders) {
mHolder = holders[0];
...
}
protected void onPostExecute(...) {
mHolder.mDownloader = null;
if (!isCancelled()) {
this.mHolder.mRowImage.setImageBitmap(image);
}
this.mHolder = null;
}
}
public class CustomListAdapter extends BaseAdapter {
#Override
public View getView(int position, ...) {
...
if (view == null) {
holder = ...
...
} else {
holder = (Holder) view.getTag();
}
...
// cancel unfinished mDownloader
if (holder.mDownloader != null) {
holder.mDownloader.cancel(false);
holder.mDownloader = null;
}
holder.mImageUrl = mImageUrls.get(position);
holder.mDownloader = new BitmapWorkerTask()
holder.mDownloader.execute(holder);
}
}
Here is a working example for this combination of Adapter + Holder + AsyncTask
[Update]
Potential problems with this solution.
Most modern android versions execute only one async task at a time. If you are fetching the images via the web you cannot download multible images at the same time. See running-parallel-asynctask#stackoverflow for details.
There may be promlems with configuration change(like orientation). See #Selvin-s comment below. I have posted this question "what-happens-with-view-references-in-unfinished-asynctask-after-orientation-chan#stackoverflow" to find out more about it.
I am using curlview for curl effect my data contain images for each page in curlview with my code i got blank pages without image which I seted in imageurllist doing json parsing how i got images instead of blank pages.
This is my code.
public class CurlActivity extends Activity {
private CurlView mCurlView;
public String cid;
public ArrayList<String>magazineidlist;
public String middata;
public String url;
public String imgurl;
public Bitmap bitmap;
public ImageLoader imageloder;
public ImageView imageView;
public ArrayList<String>imageurllist;
public GridImageAdapter gadapter;
public CurlActivity c;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_curl);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
getAllMagazineById();
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
if(bundle!=null){
cid = bundle.getString("mid");
Log.d("magazine id", cid);
}
int index = 0;
if (getLastNonConfigurationInstance() != null) {
index = (Integer) getLastNonConfigurationInstance();
}
mCurlView = (CurlView) findViewById(R.id.curl);
}
#Override
public void onPause() {
super.onPause();
mCurlView.onPause();
}
#Override
public void onResume() {
super.onResume();
mCurlView.onResume();
}
#Override
public Object onRetainNonConfigurationInstance() {
return mCurlView.getCurrentIndex();
}
/**
* Bitmap provider.
*/
private class PageProvider implements CurlView.PageProvider {
// Bitmap resources.
private int[] mBitmapIds = { R.layout.sample};
//LinearLayout llout = (LinearLayout) findViewById(R.layout.sample);
#SuppressWarnings("unused")
//ImageView imageView = (ImageView) findViewById(R.id.imageviewsample);
#Override
public int getPageCount() {
return imageurllist.size();
}
private Bitmap loadBitmap(int width, int height, int index) {
LayoutInflater inflater =
(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Log.d("index",String.valueOf(index));
View v = inflater.inflate((mBitmapIds[index]),null);
v.measure(
MeasureSpec.makeMeasureSpec(width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight()
,Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
#Override
public void updatePage(CurlPage page, int width, int height, int index) {
switch (index) {
// First case is image on front side, solid colored back.
default:
Bitmap front = loadBitmap(width, height, 0);
page.setTexture(front, CurlPage.SIDE_FRONT);
page.setColor(Color.rgb(180, 180, 180), CurlPage.SIDE_BACK);
break;
/*// Third case is images on both sides.
case 2: {
Bitmap front = loadBitmap(width, height, 1);
Bitmap back = loadBitmap(width, height, 3);
page.setTexture(front, CurlPage.SIDE_FRONT);
page.setTexture(back, CurlPage.SIDE_BACK);
break;
}
// Fourth case is images on both sides - plus they are blend against
// separate colors.
case 3: {
Bitmap front = loadBitmap(width, height, 2);
Bitmap back = loadBitmap(width, height, 1);
page.setTexture(front, CurlPage.SIDE_FRONT);
page.setTexture(back, CurlPage.SIDE_BACK);
page.setColor(Color.argb(127, 170, 130, 255),
CurlPage.SIDE_FRONT);
page.setColor(Color.rgb(255, 190, 150), CurlPage.SIDE_BACK);
break;
}
// Fifth case is same image is assigned to front and back. In this
// scenario only one texture is used and shared for both sides.
case 4:
Bitmap front = loadBitmap(width, height, 0);
page.setTexture(front, CurlPage.SIDE_BOTH);
page.setColor(Color.argb(127, 255, 255, 255),
CurlPage.SIDE_BACK);
break;*/
}
}
}
/**
* CurlView size changed observer.
*/
class SizeChangedObserver implements CurlView.SizeChangedObserver {
#Override
public void onSizeChanged(int w, int h) {
if (w > h) {
mCurlView.setViewMode(CurlView.SHOW_TWO_PAGES);
mCurlView.setMargins(.1f, .05f, .1f, .05f);
} else {
mCurlView.setViewMode(CurlView.SHOW_ONE_PAGE);
//mCurlView.setMargins(.1f, .1f, .1f, .1f);
}
}
}
public Bitmap GetBitmapfromUrl(String scr) {
try {
URL url=new URL(scr);
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input=connection.getInputStream();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeStream(input, null, options);
// Bitmap bmp = BitmapFactory.decodeStream(input);
return bitmap;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public void getAllMagazineById() {
new AsyncTask<Void, Void, String>() {
ProgressDialog mProgressDialog;
protected void onPostExecute(String result) {
mProgressDialog.dismiss();
magazineidlist = new ArrayList<String>();
imageurllist = new ArrayList<String>();
//imageloder = new ImageLoader(CurlActivity.this);
// LayoutInflater factory = LayoutInflater.from(CurlActivity.this);
// View child = factory.inflate(R.layout.sample, null);
// imageView = (ImageView)child.findViewById(R.id.imageviewsample);
//imageView = (ImageView)findViewById(R.id.imageviewsample);
try {
JSONObject jsob = new JSONObject(result.toString());
if (jsob.getString("msg").equalsIgnoreCase("Success")) {
JSONArray datajson = jsob.getJSONArray("data");
for (int i = 0; i < datajson.length(); i++) {
JSONObject c = datajson.getJSONObject(i);
middata = c.getString("magazine_id");
imgurl = c.getString("image_url");
magazineidlist.add(middata);
imageurllist.add(imgurl);
Log.d("imageurllist value at index" +i, imageurllist.get(i));
//imageloder.DisplayImage(imageurllist.get(i),imageView);
String url = imageurllist.get(i);
Log.d("url val", url);
}
gadapter = new GridImageAdapter(c, imageurllist);
mCurlView.setPageProvider(new PageProvider());
mCurlView.setSizeChangedObserver(new SizeChangedObserver());
mCurlView.setCurrentIndex(0);
mCurlView.setBackgroundColor(0xFF202830);
} else if(jsob.getString("msg").equalsIgnoreCase("Failure")) {
System.out.println("not a valid data");
}
else
{
System.out.println("error");
}
} catch (Exception e) {
Log.e("error", "" + e);
}
}
private void startActivity(Intent i) {
// TODO Auto-generated method stub
}
#Override
protected String doInBackground(Void... arg0) {
// Creating service handler class instance
try {
HttpPost httppost1 = null;
HttpClient httpclient1 = new DefaultHttpClient();
httppost1 = new HttpPost(JsonKey.MAIN_URL);
// Add your data
List<NameValuePair> nameValuePairs1 = new ArrayList<NameValuePair>(
2);
nameValuePairs1.add(new BasicNameValuePair("action",
"GetMagazinePageImagesbyid"));
nameValuePairs1.add(new BasicNameValuePair("iMagezineId",
cid));
httppost1.setEntity(new UrlEncodedFormEntity(
nameValuePairs1));
// Execute HTTP Post Request
HttpResponse response1 = httpclient1.execute(httppost1);
BufferedReader in1 = new BufferedReader(
new InputStreamReader(response1.getEntity()
.getContent()));
StringBuffer sb1 = new StringBuffer("");
String line1 = "";
while ((line1 = in1.readLine()) != null) {
sb1.append(line1);
}
in1.close();
Log.e(" Get All magazine original data", sb1.toString());
return sb1.toString();
} catch (Exception e) {
Log.e("Get All magazine response problem", "" + e);
return " ";
}
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
mProgressDialog = new ProgressDialog(CurlActivity.this);
mProgressDialog.setTitle("");
mProgressDialog.setCanceledOnTouchOutside(false);
mProgressDialog.setMessage("Please Wait...");
mProgressDialog.show();
}
}.execute();
}
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
// Log exception
return null;
}
}
Bitmap drawable_from_url(String url) throws java.net.MalformedURLException, java.io.IOException {
Bitmap x;
HttpURLConnection connection = (HttpURLConnection)new URL(url) .openConnection();
connection.setRequestProperty("User-agent","Mozilla/4.0");
connection.connect();
InputStream input = connection.getInputStream();
x = BitmapFactory.decodeStream(input);
return x;
}
public class GridImageAdapter extends BaseAdapter {
public Context mContext;
// public final String[] web;
// final int ImageId[];
public CurlActivity activity;
public ImageLoader imageloader;
// Constructor
public GridImageAdapter(CurlActivity c, ArrayList<String> imageUrl) {
// TODO Auto-generated constructor stub
mContext = c;
imageurllist = imageUrl;
imageloader = new ImageLoader(CurlActivity.this);
}
public int getCount() {
return imageurllist.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.sample, null);
ImageView img = (ImageView) grid.findViewById(R.id.imageviewsample);
imageloader.DisplayImage(imageurllist.get(position), img);
}
/*
* ImageView imageView; if (convertView == null) { imageView = new
* ImageView(mContext); imageView.setLayoutParams(new
* GridView.LayoutParams(85, 85));
* imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
* imageView.setPadding(8, 8, 8, 8); }
*/else {
grid = (View) convertView;
}
/*
* imageView.setImageResource(mThumbIds[position]); return
* imageView;
*/
return grid;
}
// Keep all Images in array
/*
* public Integer[] mThumbIds = { R.drawable.nightlife,
* R.drawable.coffee, R.drawable.shopping, R.drawable.seeanddo,
*
* };
*/
public Bitmap StringToBitMap(String encodedString) {
try {
byte[] encodeByte = Base64
.decode(encodedString, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(encodeByte, 0,
encodeByte.length);
return bitmap;
} catch (Exception e) {
e.getMessage();
return null;
}
}
}
}
I want to crate curlview with dynemic data. I used imageview to display image into curlview because my api contain image in data. but image is not displayed into imageview how i do this?
Below is my code.
public class CurlActivity extends Activity {
private CurlView mCurlView;
public String cid;
public ArrayList<String>magazineidlist;
public String middata;
public String url;
public String imgurl;
public Bitmap bitmap;
public ImageLoader imageloder;
public ImageView imageView;
public ArrayList<String>imageurllist;
public GridImageAdapter gadapter;
public CurlActivity c;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_curl);
gadapter = new GridImageAdapter(c, imageurllist);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
getAllMagazineById();
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
if(bundle!=null){
cid = bundle.getString("mid");
Log.d("magazine id", cid);
}
int index = 0;
if (getLastNonConfigurationInstance() != null) {
index = (Integer) getLastNonConfigurationInstance();
}
mCurlView = (CurlView) findViewById(R.id.curl);
}
#Override
public void onPause() {
super.onPause();
mCurlView.onPause();
}
#Override
public void onResume() {
super.onResume();
mCurlView.onResume();
}
#Override
public Object onRetainNonConfigurationInstance() {
return mCurlView.getCurrentIndex();
}
/**
* Bitmap provider.
*/
private class PageProvider implements CurlView.PageProvider {
// Bitmap resources.
private int[] mBitmapIds = { R.layout.sample};
//LinearLayout llout = (LinearLayout) findViewById(R.layout.sample);
#SuppressWarnings("unused")
//ImageView imageView = (ImageView) findViewById(R.id.imageviewsample);
#Override
public int getPageCount() {
return imageurllist.size();
}
private Bitmap loadBitmap(int width, int height, int index) {
LayoutInflater inflater =
(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Log.d("index",String.valueOf(index));
View v = inflater.inflate(mBitmapIds[index],null);
v.measure(
MeasureSpec.makeMeasureSpec(width,MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight()
,Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
#Override
public void updatePage(CurlPage page, int width, int height, int index) {
switch (index) {
// First case is image on front side, solid colored back.
default:
Bitmap front = loadBitmap(width, height, 0);
page.setTexture(front, CurlPage.SIDE_FRONT);
page.setColor(Color.rgb(180, 180, 180), CurlPage.SIDE_BACK);
break;
/*// Third case is images on both sides.
case 2: {
Bitmap front = loadBitmap(width, height, 1);
Bitmap back = loadBitmap(width, height, 3);
page.setTexture(front, CurlPage.SIDE_FRONT);
page.setTexture(back, CurlPage.SIDE_BACK);
break;
}
// Fourth case is images on both sides - plus they are blend against
// separate colors.
case 3: {
Bitmap front = loadBitmap(width, height, 2);
Bitmap back = loadBitmap(width, height, 1);
page.setTexture(front, CurlPage.SIDE_FRONT);
page.setTexture(back, CurlPage.SIDE_BACK);
page.setColor(Color.argb(127, 170, 130, 255),
CurlPage.SIDE_FRONT);
page.setColor(Color.rgb(255, 190, 150), CurlPage.SIDE_BACK);
break;
}
// Fifth case is same image is assigned to front and back. In this
// scenario only one texture is used and shared for both sides.
case 4:
Bitmap front = loadBitmap(width, height, 0);
page.setTexture(front, CurlPage.SIDE_BOTH);
page.setColor(Color.argb(127, 255, 255, 255),
CurlPage.SIDE_BACK);
break;*/
}
}
}
/**
* CurlView size changed observer.
*/
class SizeChangedObserver implements CurlView.SizeChangedObserver {
#Override
public void onSizeChanged(int w, int h) {
if (w > h) {
mCurlView.setViewMode(CurlView.SHOW_TWO_PAGES);
mCurlView.setMargins(.1f, .05f, .1f, .05f);
} else {
mCurlView.setViewMode(CurlView.SHOW_ONE_PAGE);
//mCurlView.setMargins(.1f, .1f, .1f, .1f);
}
}
}
public Bitmap GetBitmapfromUrl(String scr) {
try {
URL url=new URL(scr);
HttpURLConnection connection=(HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input=connection.getInputStream();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeStream(input, null, options);
// Bitmap bmp = BitmapFactory.decodeStream(input);
return bitmap;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public void getAllMagazineById() {
new AsyncTask<Void, Void, String>() {
ProgressDialog mProgressDialog;
protected void onPostExecute(String result) {
mProgressDialog.dismiss();
magazineidlist = new ArrayList<String>();
imageurllist = new ArrayList<String>();
//imageloder = new ImageLoader(CurlActivity.this);
// LayoutInflater factory = LayoutInflater.from(CurlActivity.this);
// View child = factory.inflate(R.layout.sample, null);
// imageView = (ImageView)child.findViewById(R.id.imageviewsample);
//imageView = (ImageView)findViewById(R.id.imageviewsample);
try {
JSONObject jsob = new JSONObject(result.toString());
if (jsob.getString("msg").equalsIgnoreCase("Success")) {
JSONArray datajson = jsob.getJSONArray("data");
for (int i = 0; i < datajson.length(); i++) {
JSONObject c = datajson.getJSONObject(i);
middata = c.getString("magazine_id");
imgurl = c.getString("image_url");
magazineidlist.add(middata);
imageurllist.add(imgurl);
Log.d("imageurllist value at index" +i, imageurllist.get(i));
//imageloder.DisplayImage(imageurllist.get(i),imageView);
String url = imageurllist.get(i);
Log.d("url val", url);
}
mCurlView.setPageProvider(new PageProvider());
mCurlView.setSizeChangedObserver(new SizeChangedObserver());
//mCurlView.setCurrentIndex(0);
mCurlView.setBackgroundColor(0xFF202830);
} else if(jsob.getString("msg").equalsIgnoreCase("Failure")) {
System.out.println("not a valid data");
}
else
{
System.out.println("error");
}
} catch (Exception e) {
Log.e("error", "" + e);
}
}
private void startActivity(Intent i) {
// TODO Auto-generated method stub
}
#Override
protected String doInBackground(Void... arg0) {
// Creating service handler class instance
try {
HttpPost httppost1 = null;
HttpClient httpclient1 = new DefaultHttpClient();
httppost1 = new HttpPost(JsonKey.MAIN_URL);
// Add your data
List<NameValuePair> nameValuePairs1 = new ArrayList<NameValuePair>(
2);
nameValuePairs1.add(new BasicNameValuePair("action",
"GetMagazinePageImagesbyid"));
nameValuePairs1.add(new BasicNameValuePair("iMagezineId",
cid));
httppost1.setEntity(new UrlEncodedFormEntity(
nameValuePairs1));
// Execute HTTP Post Request
HttpResponse response1 = httpclient1.execute(httppost1);
BufferedReader in1 = new BufferedReader(
new InputStreamReader(response1.getEntity()
.getContent()));
StringBuffer sb1 = new StringBuffer("");
String line1 = "";
while ((line1 = in1.readLine()) != null) {
sb1.append(line1);
}
in1.close();
Log.e(" Get All magazine original data", sb1.toString());
return sb1.toString();
} catch (Exception e) {
Log.e("Get All magazine response problem", "" + e);
return " ";
}
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
mProgressDialog = new ProgressDialog(CurlActivity.this);
mProgressDialog.setTitle("");
mProgressDialog.setCanceledOnTouchOutside(false);
mProgressDialog.setMessage("Please Wait...");
mProgressDialog.show();
}
}.execute();
}
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
// Log exception
return null;
}
}
Bitmap drawable_from_url(String url) throws java.net.MalformedURLException, java.io.IOException {
Bitmap x;
HttpURLConnection connection = (HttpURLConnection)new URL(url) .openConnection();
connection.setRequestProperty("User-agent","Mozilla/4.0");
connection.connect();
InputStream input = connection.getInputStream();
x = BitmapFactory.decodeStream(input);
return x;
}
public class GridImageAdapter extends BaseAdapter {
public Context mContext;
// public final String[] web;
// final int ImageId[];
public CurlActivity activity;
public ImageLoader imageloader;
// Constructor
public GridImageAdapter(CurlActivity c, ArrayList<String> imageUrl) {
// TODO Auto-generated constructor stub
mContext = c;
imageurllist = imageUrl;
imageloader = new ImageLoader(CurlActivity.this);
}
public int getCount() {
return imageurllist.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.sample, null);
ImageView img = (ImageView) grid.findViewById(R.id.imageviewsample);
imageloader.DisplayImage(imageurllist.get(position), img);
}
/*
* ImageView imageView; if (convertView == null) { imageView = new
* ImageView(mContext); imageView.setLayoutParams(new
* GridView.LayoutParams(85, 85));
* imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
* imageView.setPadding(8, 8, 8, 8); }
*/else {
grid = (View) convertView;
}
/*
* imageView.setImageResource(mThumbIds[position]); return
* imageView;
*/
return grid;
}
// Keep all Images in array
/*
* public Integer[] mThumbIds = { R.drawable.nightlife,
* R.drawable.coffee, R.drawable.shopping, R.drawable.seeanddo,
*
* };
*/
public Bitmap StringToBitMap(String encodedString) {
try {
byte[] encodeByte = Base64
.decode(encodedString, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(encodeByte, 0,
encodeByte.length);
return bitmap;
} catch (Exception e) {
e.getMessage();
return null;
}
}
}
}
I want to set a TextView with SpannableString which is from the method below:
Html.fromHtml(String source, Html.ImageGetter imageGetter,
Html.TagHandler tagHandler)
But the ImageGetter here need to override the method below:
public abstract Drawable getDrawable(String source)
Because I need to get the drawable from the internet, I have to do it asynchronously and seems it is not.
How to make it work?
Thanks.
These guys did a great job, this is my solution using Square's Picasso library:
//...
final TextView textView = (TextView) findViewById(R.id.description);
Spanned spanned = Html.fromHtml(getIntent().getStringExtra(EXTRA_DESCRIPTION),
new Html.ImageGetter() {
#Override
public Drawable getDrawable(String source) {
LevelListDrawable d = new LevelListDrawable();
Drawable empty = getResources().getDrawable(R.drawable.abc_btn_check_material);;
d.addLevel(0, 0, empty);
d.setBounds(0, 0, empty.getIntrinsicWidth(), empty.getIntrinsicHeight());
new ImageGetterAsyncTask(DetailActivity.this, source, d).execute(textView);
return d;
}
}, null);
textView.setText(spanned);
//...
class ImageGetterAsyncTask extends AsyncTask<TextView, Void, Bitmap> {
private LevelListDrawable levelListDrawable;
private Context context;
private String source;
private TextView t;
public ImageGetterAsyncTask(Context context, String source, LevelListDrawable levelListDrawable) {
this.context = context;
this.source = source;
this.levelListDrawable = levelListDrawable;
}
#Override
protected Bitmap doInBackground(TextView... params) {
t = params[0];
try {
Log.d(LOG_CAT, "Downloading the image from: " + source);
return Picasso.with(context).load(source).get();
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(final Bitmap bitmap) {
try {
Drawable d = new BitmapDrawable(context.getResources(), bitmap);
Point size = new Point();
((Activity) context).getWindowManager().getDefaultDisplay().getSize(size);
// Lets calculate the ratio according to the screen width in px
int multiplier = size.x / bitmap.getWidth();
Log.d(LOG_CAT, "multiplier: " + multiplier);
levelListDrawable.addLevel(1, 1, d);
// Set bounds width and height according to the bitmap resized size
levelListDrawable.setBounds(0, 0, bitmap.getWidth() * multiplier, bitmap.getHeight() * multiplier);
levelListDrawable.setLevel(1);
t.setText(t.getText()); // invalidate() doesn't work correctly...
} catch (Exception e) { /* Like a null bitmap, etc. */ }
}
}
My 2 cents... Peace!
Now I'm using an AsyncTask to download the images in the ImageGetter:
Spanned spannedContent = Html.fromHtml(htmlString, new ImageGetter() {
#Override
public Drawable getDrawable(String source) {
new ImageDownloadAsyncTask().execute(textView, htmlString, source);
return null;
}
}, null);
And set the text again into the TextView when the image has been downloaded.
Now it works. But It failed when I tried to do the TextView.postInvalidate() to redraw the downloaded images. I have to do setText() again in the AsyncTask.
Does anyone know why?
Here's my code that grabs all images in the html string (it's simplified from the original, so I hope it works):
private HashMap<String, Drawable> mImageCache = new HashMap<String, Drawable>();
private String mDescription = "...your html here...";
private void updateImages(final boolean downloadImages) {
if (mDescription == null) return;
Spanned spanned = Html.fromHtml(mDescription,
new Html.ImageGetter() {
#Override
public Drawable getDrawable(final String source) {
Drawable drawable = mImageCache.get(source);
if (drawable != null) {
return drawable;
} else if (downloadImages) {
new ImageDownloader(new ImageDownloader.ImageDownloadListener() {
#Override
public void onImageDownloadComplete(byte[] bitmapData) {
Drawable drawable = new BitmapDrawable(getResources(),
BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length));
try {
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
} catch (Exception ex) {}
mImageCache.put(source, drawable);
updateImages(false);
}
#Override
public void onImageDownloadFailed(Exception ex) {}
}).execute(source);
}
return null;
}
}, null);
tvDescription.setText(spanned);
}
So basically what happens here is the ImageGetter will make a request for every image in the html description. If that image isn't in the mImageCache array and downloadImages is true, we run an async task to download that image. Once it has completed, we add the drawable into the hashmap, and then make a call to this method again (but with downloadImages as false so we don't risk an infinite loop), where the image will be able to be grabbed with the second attempt.
And with that, you'll need the ImageDownloader class that I used:
public class ImageDownloader extends AsyncTask {
public interface ImageDownloadListener {
public void onImageDownloadComplete(byte[] bitmapData);
public void onImageDownloadFailed(Exception ex);
}
private ImageDownloadListener mListener = null;
public ImageDownloader(ImageDownloadListener listener) {
mListener = listener;
}
protected Object doInBackground(Object... urls) {
String url = (String)urls[0];
ByteArrayOutputStream baos = null;
InputStream mIn = null;
try {
mIn = new java.net.URL(url).openStream();
int bytesRead;
byte[] buffer = new byte[64];
baos = new ByteArrayOutputStream();
while ((bytesRead = mIn.read(buffer)) > 0) {
if (isCancelled()) return null;
baos.write(buffer, 0, bytesRead);
}
return new AsyncTaskResult<byte[]>(baos.toByteArray());
} catch (Exception ex) {
return new AsyncTaskResult<byte[]>(ex);
}
finally {
Quick.close(mIn);
Quick.close(baos);
}
}
protected void onPostExecute(Object objResult) {
AsyncTaskResult<byte[]> result = (AsyncTaskResult<byte[]>)objResult;
if (isCancelled() || result == null) return;
if (result.getError() != null) {
mListener.onImageDownloadFailed(result.getError());
}
else if (mListener != null)
mListener.onImageDownloadComplete(result.getResult());
}
}