I am creating an app to fetch XKCD comics (just for learning purpose). I am using JSoup to fetch comic title and url of the image and Universal Image Loader to post the image in ImageView. However I'm facing some problems. Here is my main activity.
public class MainActivity extends Activity {
private static final String TAG = "MyApp";
ImageView xkcdImgIV;
TextView titleTV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
xkcdImgIV=(ImageView) findViewById(R.id.xkcdImgIV);
titleTV=(TextView) findViewById(R.id.titleTV);
try{
new AsyncImg().execute(new String[]{"http://www.xkcd.com/"});
} catch(NullPointerException e){
Log.d(TAG,"Null pointer exception")
}
}
private class AsyncImg extends AsyncTask<String,Void,Void>{
Document doc;
Elements elXkcdTitle;
Elements elXkcdImgUrl;
#Override
protected Void doInBackground(String... arg) {
try {
doc = Jsoup.connect(arg[0]).timeout(0).get();
elXkcdTitle=doc.select("#ctitle");
elXkcdImgUrl=doc.select("#comic img");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result) {
titleTV.setText(elXkcdTitle.first().text());
ImageLoader imageLoader = ImageLoader.getInstance();
imageLoader.init( ImageLoaderConfiguration.createDefault(getApplicationContext() ));
imageLoader.displayImage(elXkcdImgUrl.first().attr("src"), xkcdImgIV);
}
}
}
There is no network activity. I've given the Internet access permission to the app. Moreover Logcat doesn't show any error. Both Jsoup and Universal Image Loader JARS have been included in build path. Feel free to ask for additional info.
Related
The following code ran on a java file on my computer gives the correct result of "/pws/client/pdf/offers-in-store-10-11-16.pdf"
String pdfLink= null;
try {
Document doc = Jsoup.connect("http://www.dunnesstores.com/offer20/food-wine/fcp-category/home").get();
Element links = doc.select("a[title=\"Download offers in store\"]").first();
System.out.println(links.attr("href"));
} catch (IOException e) {
//e.printStackTrace();
}
However when I run the code on my android device in an app where it is activated by the button press,I get a null pointer exception on "pdfLink=links.attr("href");" so it isnt finding the link "/pws/client/pdf/offers-in-store-10-11-16.pdf" for whatever reason.In my android app the code is on a onclick listener of a button and I have stepped through the code,it does activate the on click and runs the right lines of code but for whatever reason JSOUP is not finding the link.Below is the android code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnFetchData = (Button) findViewById(R.id.buttonTest);
btnFetchData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new FetchWebsiteData().execute();
}
});
}
private class FetchWebsiteData extends AsyncTask<Void, Void, Void> {
private String pdfLink = "didnt work";
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
try {
Document doc = Jsoup.connect("http://www.dunnesstores.com/offer20/food-wine/fcp-category/home").get();
//Elements links = doc.select("a[title=\"Download offers in store\"]");
Element links = doc.select("a[title=\"Download offers in store\"]").first();
pdfLink=links.attr("href");
} catch (IOException e) {
//e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
TextView txttitle = (TextView) findViewById(R.id.resultTextView);
txttitle.setText(pdfLink);
}
}
}
the mobile browser user-agent differs from the desktop browser; therefore, the HTML responses differ. In order to get the same result you have to set a desktop user-agent. Change this line :
Document doc = Jsoup.connect("http://www.dunnesstores.com/offer20/food-wine/fcp-category/home").get();
to:
Document doc = Jsoup.connect("http://www.dunnesstores.com/offer20/food-wine/fcp-category/home").userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0").get();
Actually It is changing but into Blank!
In my App, i going to get my Images-Path from Database and show them in main activity. this process achieves by selecting thumbnails of images in DialogFragment and sending their Record ID to main Activity withing an Interface for Communicating between Fragment-Activity.
at this point i am going to use an Asynctask inner class to get FilePath of selected Image and Show it to ImageView.
everythings works perfectly EXCEPT that the ImageView does not show it properly and it just show blank!
P.S.: the FilePath is Correct, i used it in onActivityResult on some place in app.
Thank you.
Main Activity code:
public class AnnotateDiagramActivity extends Activity implements Communicator {
#Override
public void respond(String data , int requestCode) {
//Passing Project ID from CPDialogFragment or PLDialogFragment
switch(requestCode) {
case OPEN_PROJECTID:
PROJECTID = Integer.valueOf(data);
loadProject(PROJECTID);
ToastShort(data);
break;
default:
break;
}
}
public class loadMainImage extends AsyncTask<Project,Integer,String>
{
#Override
protected String doInBackground(Project... params) {
return project.GetFilePath();
}
protected void onPostExecute( String result) {
//here is my main issue:
fragmentView.setImageBitmap(new ImageDecoder().decodeFile(new File(project.GetFilePath())));
fragmentView.postInvalidate();
}
}
public void loadProject(int ID)
{
project = new Project();
project= expertDbHelper.getProject(ID);
SharedPreferences openedProject = getSharedPreferences("openedProject", 0);
SharedPreferences.Editor projectEditor = openedProject.edit();
projectEditor.putInt("id",project.GetID());
projectEditor.putString("filePath",project.GetFilePath());
projectEditor.commit();
new loadMainImage().execute(project);
}
}
EDIT For Verifying on Returning Image From File Path:
protected void onPostExecute( String result) {
ImageDecoder imageDecoder = new ImageDecoder();
Bitmap bmp = null;
File file =new File(result);
if(file.isFile()) {
bmp=imageDecoder.decodeFile(file,500);
fragmentView.setImageBitmap(bmp);
fragmentView.postInvalidate();
}
else
{ Log.e("Async Task Is File: " ,String.valueOf(file.isFile()));}
}
I've found that my Image does not set properly due to some criteria that calculated from previous loaded image, so i check my code and find (layout boolean parameter) in my code that needs to be reset.
protected void onPostExecute( String result) {
ImageDecoder imageDecoder = new ImageDecoder();
Bitmap bmp = null;
File file =new File(result);
Log.e("Async Task Result: " ,result);
if(file.isFile()) {
bmp=imageDecoder.decodeFile(file,500);
fragmentView.reset();
fragmentView.recycle();
fragmentView.layout= false;
fragmentView.setImageBitmap(bmp);
}
else
{
Log.e("Async Task Is File: " ,String.valueOf(file.isFile()));
}
}
I just wanted to Grab an image from a URL and to display it in an imageview
The code:
public class MainActivity extends Activity {
// declare internal using controls
private TextView txtUrl;
private ImageView imgView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgView =(ImageView)findViewById(R.id.imageView1);
Drawable drawable=null;
drawable = grabImageFromUrl("http://blog.sptechnolab.com/wp-content/uploads/2011/02/c2.jpg");
imgView.setImageDrawable(drawable);
}
private Drawable grabImageFromUrl(String url) {
try {
return Drawable.createFromStream((InputStream)new URL(url).getContent(), "src");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
I am having this error:
09-04 20:34:18.712: E/AndroidRuntime(1156): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: android.os.NetworkOnMainThreadException
I would appreciate your help please be specific in your answers
Is your app configured with Internet permissions? That is, do you have the following in your app's manifest?
<uses-permission android:name="android.permission.INTERNET" />
FOLLOW UP: Also, the error seems to be saying you shouldn't do network access on your app's UI thread. It's generally a bad practice to do any long blocking I\O on your app's UI thread. Try using an AnycTask, or you might even have a look at some of the code in LazyList.
EXAMPLE: add this as an inner class to your activity:
private class DownloadTask extends AsyncTask<Void, Void, Drawable>{
private final String mUrl;
public DownloadTask(String url){
mUrl = url;
}
#Override
protected Drawable doInBackground(Void... params) {
try {
return Drawable.createFromStream((InputStream)new URL(mUrl).getContent(), "src");
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(Drawable result){
((ImageView)findViewById(R.id.imageView1)).setImageDrawable(result);
}
}
Then call it like this from your onCreate:
new DownloadTask(url).execute();
Take a look at this question in stack also :
Display image from URL - sizing and screen orientation problems
It could be helpful.
The easy way is to simply use setImageURI:
imgView = (ImageView)findViewById(R.id.imageView1);
imgView.setImageURI(Uri.parse("http://blog.sptechnolab.com/wp-content/uploads/2011/02/c2.jpg"));
As noted in the docs though:
This does Bitmap reading and decoding on the UI thread, which can cause a latency hiccup.
If that's a concern, you probably want to decode in an AsyncTask as suggested by another answer.
Am develop the Frame application. For that i want to display images(frames) from url. the url has more than 50 images. For that i use gridview but it lacks some points such as,
1.It speeds very slow to load images.
2.We declare the name and size of the images at code time so that we dont add images to the url after publishing the applicaton.
I need solution for these asap. Please anyone give me suggestion.
Use below link of lazy loading listview, this will help you.
Lazy Loading ListView
Use Above link Code and Add another activity and another layout for display selected image, if u have any issue than tell me, i will put full code here.
1.It speeds very slow to load images.
It will depend on You bandwidth and device Cache.
2. We declare the name and size of the images at code time so that we dont add images to the url after publishing the application.
You can have predefine URL so at code time you can append the image name to url.and once you have URL ready using AsyncTask download images one by one \
The below snippets will help you.
DownloadHelper.java
public interface DownloadHelper
{
public void OnSucess(Bitmap bitmap);
public void OnFailure(String response);
}
MainActivity.java
public class GalleryExample extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
DownloadHelper downloadHelper = new DownloadHelper()
{
#Override
public void OnSucess(Bitmap bitmap)
{
ImageView imageView=(ImageView)findViewById(R.id.imageView);
imageView.setImageBitmap(bitmap);
}
#Override
public void OnFailure(String response)
{
Toast.makeText(context, response, Toast.LENGTH_LONG).show();
}
};
new MyTask(this,downloadHelper).execute("image url");
}
MyTask.java
public class DownloadTask extends AsyncTask<String, Integer, Object>
{
private Context context;
private DownloadHelper downloadHelper;
private ProgressDialog dialog;
public DownloadTask(Context context,DownloadHelper downloadHelper)
{
this.context = context;
}
#Override
protected void onPreExecute()
{
dialog = new ProgressDialog(context);
dialog.setTitle("Please Wait");
dialog.setMessage("Fetching Data!!");
dialog.setCancelable(false);
dialog.show();
super.onPreExecute();
}
#Override
protected Object doInBackground(String... params)
{
URL aURL = new URL(myRemoteImages[position]);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/* Decode url-data to a bitmap. */
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
return bm;
}
#Override
protected void onPostExecute(Object result)
{
dialog.dismiss();
if (result != null)
{
downloadHelper.OnSucess((Bitmap)result);
}
else
{
downloadHelper.OnFailure("Error in Downloading Data!!");
}
super.onPostExecute(result);
}
}
This is my AsyncTask, called from getView of an adapter:
class LoadImage extends AsyncTask<Object,Void,String>{
private ImageView imv;
private String path;
public LoadImage(ImageView imv) {
this.imv = imv;
}
Bitmap userAvatarStream = null ;
Bitmap IconStream = null;
URL IconURL;
ProgressDialog dialog;
#Override
protected void onPreExecute(){
//Setting all the variables by getting the ids from the layout
return;
}
#Override
protected String doInBackground(Object... params) {
try {
IconURL = new URL(cr.ImageUrl);
IconStream = BitmapFactory.decodeStream(IconURL.openConnection().getInputStream());
}
catch (MalformedURLException e){
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(String result){
// ImageView user_avatar = (ImageView)v.findViewById(R.id.follower_user_avatar);
imv.setImageBitmap(IconStream);
return;
}
The problem that I get here is that the images keep loading. Lets say I scroll down and the images go away to be refreshed again if I scroll up the list. It keeps making calls to get the images. This behaviour is obviously undesirable except at one place that if the internet on your cell-phone goes down and comes up again, this would help to auto-load the images. But, in the current state even that is crashing as it keeps making calls. How to stop AsyncTask from doing that?
Just cache you images to filesystem or memory.
Each time you scroll the list getView is called. If you put the image loading method on getView and didn't use Image Caching then it'll download the images again and again. There are some opensource image loader for list with caching support.
One of them is droidFu. It supports two level of caching. Filesystem and memory. Get droidFu from following link.
https://github.com/kaeppler/droid-fu
Try a boolean flag to keep the check whether the image was loaded successfully or not.
If it was not then only make a call to Load Image Asynctask.
You may need to use a boolean array to keep the track if there are more than one row in adapter.
Try this code:
class performBackgroundTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog.setMessage("Please wait ...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(String... arg0) {
callxmlparser();
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (ringtoneNamelist != null && ringtoneNamelist.size() > 0) {
songslist.setAdapter(new Songslist());
} else {
Toast.makeText(SongsList.this,"Network signal speed is too slow\ncannot parse the data from the server\n Please try again", Toast.LENGTH_LONG).show();
}
dialog.dismiss();
}
}