Android Volley display SVG image - android

In my Android App I download text-content from my website and store it in my mysql database. Now I want to download and cache images from the same website. With AndroidVolley's <com.android.volley.toolbox.NetworkImageView, downloading normal pictures works pretty good. But I want to download SVG-vector images, cache them and display in my App. So far this is not possible in Android Volley...
I already tried to download the SVGs with AndroidVolley as a String and then put them in a svg-android element (See here), but svg-android did never show my image. It seems, that it can't display SVGs created by Inkscape...
Does anybody know a simple way, how to download these files and display them in a view?
Thanks
// UPDATE 27.3.2015 //
So this is my solution:
With Android Volley I set a StringRequest to access my SVG-Image as a String. The AndroidSVG library (don't mix up with the svg-android library) may convert this String into a SVG-Object and put it into an SVGImageView-View. Here is an example Code how it worked:
StringRequest stringRequest = new StringRequest("http://******/image.svg",new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
SVG svg = SVG.getFromString(response);
View view = getView();
if(view != null){
SVGImageView target = (SVGImageView)view.findViewById(catID);
target.setSVG(svg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
},new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(Globals.TAG,"Fehler "+error);
}
});
RequestQueue queue = Volley.newRequestQueue(mContext);
stringRequest.setShouldCache(true);
queue.add(stringRequest);
Thanks a lot!

Here is a slightly different solution because I wanted to store the image loaded in a variable for reuse several times.
So I just changed the source Volley replacing "private" with "protected" for the method
protected Response <Bitmap> doParse (NetworkResponse response)
Then I created a class that inherits from ImageRequest and which uses the AndroidSVG library.
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.widget.ImageView;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.ImageRequest;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGParseException;
/**
* Version modifiée de ImageRequest de Volley pour gérer aussi les images SVG
*/
public class MultiFormatImageRequest extends ImageRequest {
final String TAG = "EE." + getClass().getSimpleName();
boolean isSVG = false;
public MultiFormatImageRequest(String url, Response.Listener<Bitmap> listener, int maxWidth, int maxHeight,
ImageView.ScaleType scaleType, Bitmap.Config decodeConfig, Response.ErrorListener errorListener) {
super(url, listener, maxWidth, maxHeight, scaleType, decodeConfig, errorListener);
String extension = url.substring(url.lastIndexOf("."));
isSVG = (extension.toUpperCase().contains("SVG"));
}
/****
* ATTENTION : "private" Response in Volley need to be changed in protected
*/
#Override
protected Response<Bitmap> doParse(NetworkResponse response) {
Bitmap image = null;
if (isSVG) {
try {
SVG svg = SVG.getFromString(new String(response.data));
int h = (int) svg.getDocumentHeight();
int w = (int) svg.getDocumentWidth();
image = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); // transparent
Canvas bmcanvas = new Canvas(image);
svg.renderToCanvas(bmcanvas);
} catch (SVGParseException ex) {
ex.printStackTrace();
}
if (image == null) {
return Response.error(new ParseError(response));
} else {
return Response.success(image, HttpHeaderParser.parseCacheHeaders(response));
}
} else
return super.doParse(response); // Volley default
}
}

You can try two things:
1. With svg-android library, you need to set
imgView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
to make it work.
2. If the first approach doesn't work, you can try using SVGImageView.

Related

Problem previewing remote PDF in Android via Glide

I'm trying to preview (thumbnail) PDF documents that are remotely, using the Glide library from bumptech, version 4.8.0.
To achieve this, following the excellent tutorial Writing a custom ModelLoader, I've written a custom ModelLoader, a custom DataFetcher for the buildLoadData method; added the AppGlideModule, implemented ModelLoaderFactory and registered my ModelLoader.
Inside the DataFetcher I've added some logic to process the following two cases:
The content is an image. Works like a charm!
The content is a PDF document. W/Glide: Load failed for https://www.testserver.net/folder/sample.pdf with size [522x600]
class com.bumptech.glide.load.engine.GlideException: Failed to load resource
One approach has been to download the PDF file locally, and then render it (this DOES work), but it adds a considerable delay when having to download a file from a url and copy it locally; on the other hand, it doesn't take advantage of Glide's use of the cache.
Should I add another extra ModelLoader to use OkHttp3 instead of Volley (default)?
Any ideas? Thanks in advance!
public final class MyModelLoader implements ModelLoader<File, InputStream> {
private final Context context;
public MyModelLoader(Context context) {
this.context = context;
}
#NonNull
#Override
public ModelLoader.LoadData<InputStream> buildLoadData(#NonNull File model, int width, int height, #NonNull Options options) {
return new ModelLoader.LoadData<>(new ObjectKey(model), new MyDataFetcher(context, model));
}
#Override
public boolean handles(#NonNull File file) {
return true;
}
}
public class MyDataFetcher implements DataFetcher<InputStream> {
#SuppressWarnings("FieldCanBeLocal")
private final Context context;
private final File file;
private InputStream inputStream;
public MyDataFetcher(Context context, File file) {
this.context = context;
this.file = file;
}
#Override
public void loadData(#NonNull Priority priority, #NonNull DataCallback<? super InputStream> callback) {
try {
if (isPdf(file)) {
//We have a PDF document in "file" -- fail (if document is remote)
try {
//render first page of document PDF to bitmap, and pass to method 'onDataReady' as a InputStream
PdfRenderer pdfRenderer = new PdfRenderer(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
PdfRenderer.Page page = pdfRenderer.openPage(0);
int width = 2048;
int height = (page.getHeight() * (width / page.getWidth()));
Bitmap pageBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
page.render(pageBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
pageBitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream);
ByteArrayInputStream stream = new ByteArrayInputStream(outputStream.toByteArray());
callback.onDataReady(stream);
} catch (IOException ignored) {}
} else {
//We have an image in "file" -- OK
FileInputStream fileInputStream = new FileInputStream(file);
callback.onDataReady(fileInputStream);
}
} catch (IOException ignored) {}
}
// checks for file content
public boolean isPdf(File f) throws IOException {
URLConnection connection = f.toURL().openConnection();
String mimeType = connection.getContentType();
return mimeType.equals("application/pdf");
}
#Override
public void cleanup() {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException ignored) {}
}
}
#Override
public void cancel() {
//empty
}
#NonNull
#Override
public Class<InputStream> getDataClass() {
return InputStream.class;
}
#NonNull
#Override
public DataSource getDataSource() {
return DataSource.REMOTE;
}
}
public class MyModelLoaderFactory implements ModelLoaderFactory<File, InputStream> {
private final Context context;
public MyModelLoaderFactory(Context context) {
this.context = context;
}
#NonNull
#Override
public ModelLoader<File, InputStream> build(#NonNull MultiModelLoaderFactory multiFactory) {
return new MyModelLoader(context);
}
#Override
public void teardown() {
//empty
}
}
#GlideModule public class MyAppGlideModule extends AppGlideModule {
#Override
public void registerComponents(#NonNull Context context, #NonNull Glide glide, Registry registry) {
registry.prepend(File.class, InputStream.class, new MyModelLoaderFactory(context));
}
}
Finally, after all of the above, the call is of the form:
GlideApp.with(image.getContext()).load("resource_url").into(image);
Where "resouce_url" could be: https://www.testserver.net/folder/sample.pdf, eg.
You can show image and video thumbnails using Glide library if you want to show a pdf thumbnail you need to use the library for it e.g. Android PdfViewer. Then instead of using ImageView use PdfView and load only the first page instead of all e.g. .pages(0). That's it.
In your xml/layout
<com.github.barteksc.pdfviewer.PDFView
android:id="#+id/pdfView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
In your class
pdfView.fromBytes(bytes)
.pages(0) //show only first page
.spacing(0)
.swipeHorizontal(false)
.enableSwipe(false)
.load();
Well, I've finally found a method to solve the problem, from another perspective.
Instead of preprocessing the pdf on client-side, using a Glide ModelLoader, I've come up with an outlier but effective subterfuge: do it on server-side.
By means of the php Imagick extension, I've modified the server api so that it automatically generates a thumbnail on the server (in the "upload.php" module), same path where the pdf is saved. Thus, assuming that we have the pdf already loaded, we do the following:
// Create thumbnail, if pdf
if ($ext == 'pdf') {
$im = new imagick($base_path.$next_id["next"].".".$ext.'[0]');
$im->setImageFormat('jpg');
header('Content-Type: image/jpeg');
file_put_contents($base_path.$next_id["next"]."_thumbnail.jpg", $im);
}
(with the help of this link on using Imagick to convert pdf to jpg: How to convert pdf to a preview image in PHP).
On the other hand, when a record is deleted, the attachments that it may have associated must also be deleted, if any. This makes it necessary to also delete the thumbnail, in the same act, as shown below:
// Remove uploaded file from server
unlink($base_path.$id.".".$ext);
// If pdf, we also have to remove the thumbnail
if ($ext == 'pdf') {
unlink($base_path.$id."_thumbnail.jpg");
}
Now we have a set of files, some jpg/png and another pdf; but this is indifferent for Glide, which will only show jpg/png images, without any problem, even if they are remotely; and of course very quickly. The code on client-side is:
/* Have a pdf file, eg. "sample.pdf", Glide will load a file
with this name: "sample_thumbnail.jpg",
that contains first page of pdf file (preview)
(A single tap on one element will download the file
and launch an intent to display it)
*/
if (item.getType().equals("jpg") || item.getType().equals("jpeg") || item.getType().equals("png")) {
Glide.with(image.getContext()).load(item.getPath()).diskCacheStrategy(DiskCacheStrategy.RESOURCE).into(image);
} else if (item.getType().equals("pdf")) {
Glide.with(image.getContext()).load(getName(item.getPath()) + "_thumbnail.jpg").diskCacheStrategy(DiskCacheStrategy.RESOURCE).into(image);
} else {
throw new Exception("File type not supported");
}
Although maybe not everyone can have Imagick on the server, in my case this solution has worked wonderfully.

How to search for images in Android Programmatically?

I have some EditTexts in my Activity.First text the for the title, second is for author.Now the user loose focus from the second edittext ie author.I want to get the images related to that content (title and author).So what I did, I concat the title and author name and make HTTP request using Volley.And I print that response.But the response is so unpredictable that I can not fetch the images from it.
try {
String googleImageUrl = "http://images.google.com/images?q=";
String query = URLEncoder.encode(title + " " + author, "utf-8");
String url = googleImageUrl + query;
Toast.makeText(context, url, Toast.LENGTH_SHORT).show();
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
post_des.setText("Response is: " + response);
Log.i("Show me something awesome dude", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
post_des.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
And the responce is like this:
Response is: <!doctype html><html itemscope="" itemtype="http://schema.org/SearchResultsPage" lang="en-IN"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><link href="/images/branding/product/ico/googleg_lodp.ico" rel="shortcut icon"><title>something something - Google Search</title><style>#gb{font:13px/27px Arial,sans-serif;height:30px}#gbz,#gbg{position:absolute;white-space:nowrap;top:0;height:30px;z-index:1000}#gbz{left:0;padding-left:4px}#gbg{right:0;padding-right:5px}#gbs{background:transparent;position:absolute;top:-999px;visibility:hidden;z-index:998;right:0}.gbto #gbs{background:#fff}#gbx3,#gbx4{background-color:#2d2d2d;background-image:none;_background-image:none;background-position:0 -138px;background-repeat:repeat-x;border-bottom:1px solid #000;font-size:24px;height:29px;_height:30px;opacity:1;filter:alpha(opacity=100);position:absolute;top:0;width:100%;z-index:990}#gbx3{left:0}#gbx4{right:0}#gbb{position:relative}#gbbw{left:0;position:absolute;top:30px;width:100%}.gbtcb{position:absolute;visibility:hidden}#gbz .gbtcb{right:0}#gbg .gbtcb{left:0}.gbxx{display:none........like wise
I was expecting to get a Html doc.
So how to make a HTTP request for images with the content(title and author).
Edit
In layman language,
Suppose I am on images.google.com, and I typed in something in search bar, and make a search, now I want the data that Google return as the Url of the images on that webpage(I am doing all this in backend not showing it to the user.)
I think it is now understandable :)
You got html but of the whole search page. You can retrieve pictures' urls with css selectors and [JSOUP library][2] (easy to use). Just go to Chrome browser and then choose Settings - More tools - Developer tools. Then click the right mouse button on a picture and choose inspect and you'll see which container is for the pictures and what div contains src url of the images and then you right click this div and choose copy css selector. Then work with the library.
But be aware, it's not practical cause if they change the page html your code will beak. You better use specific api for this purpose, like Google Custom Search API as it was suggested in comments above.
To put image into UI you need to get its url address and then you can use Glide or Picasso or even Volley
// Retrieves an image with Volley specified by the URL, displays it in the UI.
ImageRequest request = new ImageRequest(url,
new Response.Listener<Bitmap>() {
#Override
public void onResponse(Bitmap bitmap) {
mImageView.setImageBitmap(bitmap);
}
}, 0, 0, null,
new Response.ErrorListener() {
public void onErrorResponse(VolleyError error) {
mImageView.setImageResource(R.drawable.image_load_error);
}
});
EDIT:
Here is CSS selector for all images on the google search page img.rg_ic. Using Jsoup and this selector you'll get access to all the image tags on the page
Jsoup example:
Document doc = Jsoup.connect(your link string).get();
Elements imgs = doc.select("img");//the selector
for (Element img : imgs) {
//add img urls to String array and then use to get imgs with them
String s = img.attr("src");
arr.add(s);
}
[![enter image description here][3]][3]
EDIT2 :
Your code with changes:
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
TextView textView;
String googleImageUrl = "https://www.google.co.in/search?biw=1366&bih=675&tbm=isch&sa=1&ei=qFSJWsuTNc-wzwKFrZHoCw&q=";
ArrayList<String> urls = new ArrayList<>();
String url;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Log.i("someething" , "something");
getImages("https://www.google.co.in/search?biw=1366&bih=675&tbm=isch&sa=1&ei=qFSJWsuTNc-wzwKFrZHoCw&q=somethingsomething");
}
});
}
private void getImages(String url) {
Document doc = null;
try{
doc = Jsoup.connect(url).get();
}catch (IOException e){
e.printStackTrace();
}
Elements imgs = doc.select("img");
System.out.println("Damn images"+imgs);
for (Element img : imgs){
Log.d("image-src", img.attr("data-src"));//changed `src` to `data-src`
}
}
}
You can get a List of google search images using Jsoup .،. see official site here https://jsoup.org/
/**
* Extract images from google as ArrayList.
*
* #param searchQuery is the string to search for
* #return returnedURLS is the List of urls
*/
private List<String> extractImagesFromGoogle(String searchQuery) throws IOException {
final String encodedSearchUrl = "https://www.google.com/search?q=" + URLEncoder.encode(searchQuery, "UTF-8") + "&source=lnms&tbm=isch&sa=X&ved=0ahUKEwiUpP35yNXiAhU1BGMBHdDeBAgQ_AUIECgB";
Document document = Jsoup.connect(encodedSearchUrl).get();
String siteResponse = document.toString();
List<String> returnedURLS = new ArrayList<String>();
// parse the object and query the values (the urls) for specific keys ("ou")
Pattern pattern = Pattern.compile("\"ou\":\"(.*?)\"");
Matcher matcher = pattern.matcher(siteResponse);
while (matcher.find()) {
returnedURLS.add(matcher.group(1));
}
return returnedURLS;
}
// Test it now:
List<String> retrievedURLS = new ArrayList<String>();
try {
retrievedURLS = extractImagesFromGoogle("pyramids");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(">> List Size: " + retrievedURLS.size());
System.out.println(">> List of images urls: " + retrievedURLS);

how to get instagram profile picture

in my app use want to put instagram profile pic in his account
how can I get the Profile Picture of a user from Instagram Programmatically
such as :
Using the Instagram API users endpoint (https://api.instagram.com/v1/users/{user-id}/?access_token=ACCESS-TOKEN
) you will receive a response like this one:
{
"data": {
"id": "1574083",
"username": "snoopdogg",
"full_name": "Snoop Dogg",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1574083_75sq_1295469061.jpg",
"bio": "This is my bio",
"website": "http://snoopdogg.com",
"counts": {
"media": 1320,
"follows": 420,
"followed_by": 3410
}
}
You can then take the profile_picture and download it using some like Facebook Fresco which will then display the image for you.
Well if you actually want the user to POST a instagram profile picture from your app you can't, instagram hasn't provided the post method for posting photos but yes you can get view and download as per the husky's answer.
Follow these steps to get profile pic in your app
Make a request to below link with username and receive the JSON data.
https://apinsta.herokuapp.com/u/USERNAME
Now parse the id of user from the data.
Now visit this link with the ID
https://i.instagram.com/api/v1/users/ID_HERE/info/
Now parse url key in hd_profile_pic_url_info object.
Load the image in ImageView using Glide.
Happy coding !
Credit to Chrisby for his server.
https://stackoverflow.com/a/49862390/9565955
Actually I'm using a method that doesn't require an Access Token the only thing your need is an username. I'll leave you the code down bellow
Step 1: MainActivity.java
Add this code in to your main activity, create a String function to named getHDProfilePicFromUsername the fuction should look like this:
///This function will return to you the url of the user profile picture
private String getHDProfilePicFromUsername(String username) throws ExecutionException, InterruptedException, JSONException {
JSONObject jObject;
String profileInfo = new getDataFromUrl(MainActivity.this).execute("https://www.instagram.com/"+username+"/?__a=1").get();
jObject= new JSONObject(profileInfo);
jObject = jObject.getJSONObject("graphql");
jObject = jObject.getJSONObject("user");
String response = jObject.getString("profile_pic_url_hd");
return response;
}
Then create an internal class inside your Activity named getDataFromUrl, the class should look like this:
private class getDataFromUrl extends AsyncTask<String, Void, String> {
Context mContext;
public getDataFromUrl(Context mContext) {
this.mContext = mContext;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(arg0[0]);
Log.e(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
return jsonStr;
} else {
Log.e(TAG, "Couldn't get json from server.");
return null;
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
String url = s.replace('|',',').split(",")[1];
Log.d(TAG, "Link: " + url);
}
}
Now you are able to get an user profile picture URL, as a bonus I'll let you the code for using that URL and get the picture in to an ImageView.
Step 2: main_activity.xml
Add an image view, the ImageView, can be custom but I recommend 1:1 scale to keep image quality. Your xml should look like this:
<ImageView
android:id="#+id/imgProfilePic"
android:scaleType="fitXY"
android:src="#drawable/ic_image_black_24dp"
android:layout_width="300dp"
android:layout_height="300dp"/>
</RelativeLayout>
Step 3: DownloadImageTask.java
Now you need to create an external class called DownloadImageTask the full code have to be like this one:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import java.io.InputStream;
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
Step 4: MainActivity.java
Now the last step will be to add your Main Activity the piece of code to load the ImageView, this code will be in your OnCreate void inside your MainActivity.java
ImageView = thumbnails = (ImageView)findItemById(R.id.imgProfilePic);
new DownloadImageTask(thumbnails).execute(getHDProfilePicFromUsername("jusnjshb"));
That's all, hope it helps I have 2 years using this code hope it helps.

How to convert image string from Firebase Database to bitmap in Android?

I am trying to retrieve photo url from Firebase and convert it to bitmap. Uploading to Firebase and retrieving images from Firebase storage to show in listview is no problem because Glide library is converting the url and placing the image into an ImageView. For a bitmap texture in OpenGL though, Glide isn't appropriate. The photo url comes out like this (key information has been altered to preserve security but the format is the same):
https://firebasestorage.googleapis.com/v0/b/api-project-123456789000.appspot.com/o/jzL123yO1ZxTZ1Se4ldYk2YD92v1%2Ffull%2F1234572738682%2Fcropped.jpg?alt=media&token=1e6cad76-1234f-4f9d-8923-7af07015da7d
In the logcat it shows the retrieved url. In that format though. I save the url to with SharedPreferences. I am using the Rajawali OpenGL framework to show a 3d model which gets it's bitmap from the image url that was saved to SharedPreferences. I use this async class to convert the url to bitmap and apply it to the 3d models texture.
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import org.rajawali3d.materials.textures.Texture;
import org.rajawali3d.materials.textures.TextureManager;
public class AsyncLoadImageTask extends AsyncTask<String, String, Bitmap> {
private final static String TAG = "AsyncTaskLoadImage";
private Texture texture;
public AsyncLoadImageTask(Texture texture) {
this.texture = texture;
}
#Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
try {
URL url = new URL(params[0]);
bitmap = BitmapFactory.decodeStream((InputStream)url.getContent());
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
texture.setBitmap(bitmap);
TextureManager.getInstance().replaceTexture(texture);
}
}
I then call this in my renderers onRender() method:
try {
//This is reference to the String containing the url
String url = UserPrefs.getCustomLabel(mContext);
new AsyncLoadImageTask(labelTex).execute(url);
} catch (Exception e) {
e.printStackTrace();
}
}
When the Rajawali framework tries to apply the converted bitmap, it says that the url string is null/empty.
This is the referenced method from UserPrefs.getCustomLabel():
public static String getCustomLabel(Context context){
SharedPreferences settings;
String text;
settings = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); //1
text = settings.getString(LABEL_KEY, null); //2
Log.d(UP_TAG, "Retrieved Url: " + text);
return text;
}
There is a very good chance that Rajawali is making an unauthenticated request to Firebase Storage. If you use the default security rules, that unauthenticated request will be denied.
The common solution is to use a so-called download URL to retrieve the image. A download URL is a publicly accessible, but unguessable, URL. You can get such URL from a Firebase Storage URL by using this code snippet from the Firebase documentation on downloading files:
storageRef.child("users/me/profile.png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
// Got the download URL for 'users/me/profile.png'
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
}
});

universal image loader wrong thumbnail in listview

This question was asked here: Universal-Image-Loader: wrong Bitmaps are attached to ImageView
I am using the the latest, 1.9.3. I implemented the solution by having this in my application class:
#Override
public void onCreate() {
super.onCreate();
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder().resetViewBeforeLoading(true).build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
.defaultDisplayImageOptions(defaultOptions)
.build();
ImageLoader.getInstance().init(config);
}
Per Android-Universal-Image-Loader doesn't keep loaded images on scroll in gridview, I load the image like so in my adapter:
ImageAware imageAware = new ImageViewAware(viewHolder.profileIV, false);
ImageLoader.getInstance().displayImage(imgUrl, imageAware);
It still doesn't work; I'm wondering if it's because I have to make a call to get the image url since the api that supplied the model data did not include an image url.
So in my adapter's getView(), before I use imageloader with the image url, I do another asynch call to get the image url, like so:
APIclient.getImageJson(getContext(), googleUrl, new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject imgJson) {
try {
JSONObject responseDataValue = imgJson.getJSONObject("responseData");
JSONArray resultsValue = responseDataValue.getJSONArray("results");
JSONObject result = resultsValue.getJSONObject(0);
String imgUrl = result.getString("url");
ImageAware imageAware = new ImageViewAware(viewHolder.profileIV, false);
ImageLoader.getInstance().displayImage(imgUrl, imageAware);
//ImageLoader.getInstance().displayImage(imgUrl, viewHolder.profileIV);
}
catch(Exception e) {
e.printStackTrace();
}
}
google url here looks like: https://ajax.googleapis.com/ajax/services/search/images?rsz=1&start=1&v=1.0&q=%22barack%20obama%22
each row would have a different url since the names are different. I don't know if the problem is still a listview recycer problem that wasn't fixed in the universal image loader library or if the culprit lies in the additional network call. How can I make the thumbnails consistent with the data next to it?
I think it's because of async call APIclient.getImageJson(...) in getView(). It's unknown time when onSuccess() callback is fired so you can call ImageLoader.getInstance().displayImage(...) for already recycled ImageView.
I can propose you join these 2 async operations (get JSON by APIclient, load image by ImageLoader) following way. Implement own ImageDoanloader which will process google JSON URLs (https://ajax.googleapis.com/ajax/services/search/images?rsz=1&start=1&v=1.0&q=%22barack%20obama%22), extract image URL and load image.
Let's introduce our own URI scheme - "json". So we know that incoming URIs like "json://..." are correspond to JSON link.
Prepare own downloader:
public class JsonImageDownloader extends BaseImageDownloader {
public static final String SCHEME_JSON = "json";
public static final String SCHEME_JSON_PREFIX = SCHEME_JSON + "://";
public JsonImageDownloader(Context context) {
super(context);
}
public JsonImageDownloader(Context context, int connectTimeout, int readTimeout) {
super(context, connectTimeout, readTimeout);
}
#Override
public InputStream getStream(String uri, Object extra) throws IOException {
if (uri.startsWith(SCHEME_JSON_PREFIX)) {
String jsonUri = uri.substring(SCHEME_JSON_PREFIX.length());
JSONObject imgJson = APIclient.getImageJson(context, jsonUri); // sync JSON loading
try {
JSONObject responseDataValue = imgJson.getJSONObject("responseData");
JSONArray resultsValue = responseDataValue.getJSONArray("results");
JSONObject result = resultsValue.getJSONObject(0);
String imgUrl = result.getString("url");
return super.getStream(imgUrl, extra);
} catch (JSONException e) {
throw new RuntimeException(e);
}
} else {
return super.getStream(uri, extra);
}
}
}
Set it into configuration
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
.imageDownloader(new JsonImageDownloader(context))
....
.build();
Use ImageLoader in getView(...) without using APIclient:
ImageAware imageAware = new ImageViewAware(viewHolder.profileIV, false);
ImageLoader.getInstance().displayImage("json://" + googleUrl, imageAware);

Categories

Resources