Retrieve only one image with Html.ImageGetter? - android

Iv'e been using the ImageGetter() interface in the Html.fromHtml() to retrieve image urls from a long html String. But since I only really need one image I don't want to go through the entire String and look for images. I would simply like to stop when I find the first image.
Any suggestions?
Html.fromHtml(html, new ImageGetter() {
#Override
public Drawable getDrawable(String source) {
item.setImageUrl(source);
return null;
}
}, null);
EDIT : for now I only retrieve the last image in the html String so the ImageGetter will only retrieve that image.
private String getLastImage(String htmlContent){
String img = "";
try{
img = htmlContent.substring(htmlContent.lastIndexOf("<img"));
}catch (Exception e) {
e.printStackTrace();
}
return img;
}

Have a boolean field in your ImageGetter. In getDrawable(), fetch the image only if the boolean is false and then set it to true; return null otherwise.
To completely avoid parsing the rest of the HTML, you can not use Html.fromHtml(). Instead you may try using XMLPullParser. Just keep pulling tags until you get an <img> tag, at which point get the value of its <src> attribute.
But you may have to handle inputs which are not strict XHTML properly.

Related

Validate Specfic URL input in EditText for android

My application is about downloading an image from a specific website e.g. www.example.com/img-...
The user will input the url for the img to the EditText field. e.g. www.example.com/img-123
My problem is that when the user inputs a wrong URL, i.e. one with no no image, it is empty e.g. www.example.com/img-222
I want to detect this and tell the user their input does not link to an image and try again.
I'm using the isValidUrl() function to detect if the input is a WEB_URL only but what I want is that when the entered url has no image, the program should tell them it is an incorrect format for url.
I'm using Jsoup.connect(url).get(); to connect to the url and get the image and save it
private boolean isValidUrl(String url) {
Pattern p = Patterns.WEB_URL;
Matcher m = p.matcher(url);
if(m.matches())
return true;
else
return false;
}
We can use android native android.webkit.URLUtil class to validate any kind of url.
URLUtil.isValidUrl(downloadImaheEditText.getText().toString());
it will return true if valid else false.
String[] schemes = {"http","https"}; //DEFAULT schemes = "http", "https", "ftp"
UrlValidator urlValidator = new UrlValidator(schemes);
if (urlValidator.isValid("http://www.google.com")) {
//url is valid
}else{
//url is invalid
}
Use Apache commons-validator URLValidator class
I tried this and it worked for me. Please find the code snippet below:
public static boolean isURL(String url) {
Pattern p = Patterns.WEB_URL;
Matcher m = p.matcher(url.toLowerCase());
return m.matches();
}

Image load in webview or not?

I'm using a webview to show image. I used the webview.loadUrl("imagepath"); these code to show image but the webview failed to load the image then i want to show my default image in the webview.
You have to add file:/// before your image Path.
Did you try with something like
// Exemple from asset folder
webview.loadUrl("file:///android_asset/mu_image.jpg");
// From external storage
String base = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
String imagePath = "file://"+ base + "/YOUR_FILE.jpg";
webview.loadUrl(base);
EDIT (after understanding the question ...)
You have to check if your web file exist
public static boolean exists(String URLName){
try {
HttpURLConnection.setFollowRedirects(false);
// note : you may also need
// HttpURLConnection.setInstanceFollowRedirects(false)
HttpURLConnection con =
(HttpURLConnection) new URL(URLName).openConnection();
con.setRequestMethod("HEAD");
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
Then 2 choices :
- The file exists, show it
- Or, show your default image
Source : Check if file exists on remote server using its URL
It is not a good practice to load image in a webview.
The solution is to use some kind of image loader and the best one for your case is VOLLEY. It provides cache and image loading functionality better then any other image loader.
Here is the link.

How to make links in a raw file clickable

I have a raw file with html content and comprising of <a href links. Right now I have referenced that raw file. Though the content displays, the links are not clickable. How do I make them clickable?
Below is the code for the same:
protected String doInBackground(final Void... params) {
try {
return Utils.readTextFile(Application.getAppContext(), R.raw.acknowledgements);
} catch (final IOException e) {
e.printStackTrace();
return null;
}
}
}
If using a TextView, you might use android:autoLink in XML or setAutoLinkMask in code to make URLs clickable. Note that this has nothing to do with <a> tags being present, it just scans for URLs (or other content such as e-mail addresses, if you enable them).

WebView and Assets problems

My current monodroid project is having two problems - one in loading from Assets and the other is a generated webpage being passed to be displayed and their inter-related which makes things more annoying!
The assets problem is simple enough, the file can't be found. My current code looks like this
Android.App.Application.SynchronizationContext.Post(delegate
{
string uri = "file:///android_asset/StyleSheet.css";
string settings = string.Empty;
using (var input = c.Assets.Open(uri))
using (StreamReader sr = new System.IO.StreamReader(input))
{
settings = sr.ReadToEnd();
}
string CSS = "<html><head><style>" + settings + "</style></head><body style='height:600px;background: url(Back-AQHA.jpg)' >";
retStr = CSS + tableData.Content + "</body></html>";
callback(retStr);
}, null);
This dies at the sr.ReadToEnd() line as the file can't be found. All the permissions are correctly set for me to be able to access the assets directory and read in.
c is just a Context passed to the method
Now, assuming that the file had be read in and passed back to the caller, it now fails to be displayed (tested this by generating a page within the app and passing it back)... The webviewer code is bog standard
public class webservice_webview : Activity
{
WebView web_view;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.webview);
string res = base.Intent.GetStringExtra("content");
if (res.Length > 0)
{
web_view = FindViewById<WebView>(Resource.Id.webviewer);
web_view.Settings.JavaScriptEnabled = true;
web_view.LoadData(res, "text/html", null);
web_view.SetWebViewClient(new websiteviewClient());
}
else
return;
}
private class websiteviewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, string url)
{
view.LoadData(url, "text/html", null);
return true;
}
}
public override bool OnKeyDown(Android.Views.Keycode keyCode, Android.Views.KeyEvent e)
{
if (keyCode == Keycode.Back && web_view.CanGoBack())
{
web_view.GoBack();
return true;
}
return base.OnKeyDown(keyCode, e);
}
}
}
When the content is passed over and rendered, all that results is a dead webpage saying that the url data;text/html;null,[generated html] may have moved or has gone. How do I get the generated page to display?
Thanks
Paul
It might be worth check your assets are in the assets folder and are marked in the properties pane as being "AndroidAsset" - also please make sure capitalisation is correct.
Assuming they are then you can just pass the assets direct to the webview using code like:
var web = FindViewById<WebView>(Resource.Id.AboutWebView);
web.LoadUrl("file:///android_asset/About/index.html");
from https://github.com/slodge/mobile-samples/blob/master/MWC/MWC.Droid/Views/About/AboutXamarinView.cs
If you do want to read in and manipulate the html text first, then try code like: Assets.Open("About/index.html") - i.e. without the file: scheme attached.
In your second sample, the code for web_view.LoadData(res, "text/html", null); looks correct - but then I'm not sure what your logic inside ShouldOverrideUrlLoading does - that looks like it might just prevent things from loading?

Need suggestion about a mixed "Uri / int id" images ambient

I have the following problem:
suppose that until now, I am using R.drawable.img to set the image in some imageviews
with
imgView.setImage(aProduct.getImgId());
the simplified product class look like this:
class Product{
int imgId;
....
public void setImgId(int id){
this.imgId=id;
}
public int getImgId(){
return this.imgId
}
...
}
my application is now "evolved" because the user can add customized products
taking the img from the camera and getting the Uri of the picture.
and to set the image on the ImageView imgView.setImgURI(Uri)
Now my question is:
what would be the best approach to have a mixed int/Uri image resources ambient?
can I obtain the Uri of a "R.drawable.img"?
I'm not sure if my question is clear, I mean:
I have to check, before to set the imageview, if my product has an Uri or an int Id,
and then make an "if" to call the appropriate method, or there is a simpler solution?
Thank you for reading, and sorry for my english.
Regards.
Your problem is that there are basically 3 types of image resources:
R.id... resources: internal resources, such as icons you put into the res folder
content URI's: local files or content provider resources such as content:// or file:///sdcard/...
remote file URL's: images on the web, such as http://...
You are looking for a way to pass around one identifier that can deal with all three. My solution was to pass around a string: either the toString() of the URI's, or just the string respresentation of the R.id integer.
I'm using the following code, for example, to deal with this and make the code work with it:
public static FastBitmapDrawable returnAndCacheCover(String cover, ImageRepresentedProductArtworkCreator artworkCreator) {
Bitmap bitmap = null;
Uri coverUri = null;
boolean mightBeUri = false;
//Might be a resId. Needs to be cached. //TODO: problem: resId of default cover may not survive across versions of the app.
try {
bitmap = BitmapFactory.decodeResource(Collectionista.getInstance().getResources(), Integer.parseInt(cover));
} catch (NumberFormatException e) {
//Not a resId after all.
mightBeUri=true;
}
if(bitmap==null || mightBeUri){
//Is not a resId. Might be a contentUri.
try {
coverUri = Uri.parse(cover);
} catch (NullPointerException ne) {
//Is null
return null;
}
}
if(coverUri!=null){
if(coverUri.getScheme().equals("content")){
//A contentUri. Needs to be cached.
try {
bitmap = MediaStore.Images.Media.getBitmap(Collectionista.getInstance().getContentResolver(), coverUri);
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
}else{
//Might be a web uri. Needs to be cached.
bitmap = loadCoverFromWeb(cover);
}
}
return new FastBitmapDrawable(bitmap);
}
You might be interested to take over the logic part. Ofcourse cover is the string in question here.
Forget android.resource:// as a replacement for the R.id... integer. Claims are going round it does not work: http://groups.google.com/group/android-developers/browse_thread/thread/a672d71dd7df4b2d
To find out how to implement loadCoverFromWeb, have a look around in other questions or ping me. This web stuff is kind of a field of it's own.
(Based on GPLv3 code out of my app Collectionista: https://code.launchpad.net/~pjv/collectionista/trunk)

Categories

Resources