1

I am having trouble loading a bitmap from a url on Android based on this answer: https://stackoverflow.com/a/8993175/1062794

I've simplified the case to the absolute minimum:

public void loadBitmap(View view) {
    Bitmap b = getBitmapFromURL("http://upload.wikimedia.org/wikipedia/en/7/70/Example.png");
}

public 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) {
        e.printStackTrace();
        return null;
    }
}

I have enabled internet access in manifest (I believe):

<uses-permission android:name="android.permission.INTERNET"/>

When I run the app it crashes with null details when it tries to run connection.connect(). Stepping through I see it tries to throw this error from StrictMode.class:

if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
    throw new NetworkOnMainThreadException();
}

This is my first day trying to make an Android app so I could be making an obvious mistake. I am using the emulator and Win7.

Community
  • 1
  • 1
Baz
  • 2,167
  • 1
  • 22
  • 27

3 Answers3

4

Starting with Android 3.0, synchronous operations can no longer be run directly from a UI thread. If you try to call the loadBitmap(View view) method directly in your onCreate() method, your application will crash when it is run on a device running Android 3.0 and later. Because loadBitmap() method is synchronous - that is, it will not return control until the image is downloaded - calling it directly will freeze the UI of your activity. This is not allowed in Android 3.0 and later; all synchronous code must be wrapped using an AsyncTask class. Using AsyncTask enables you to perform background tasks in a separate thread and then return the result in a UI thread. That way, you can perform background operations without needing to handle complex threading issues. To call the loadBitamp() method asynchronously, you need to wrap the code in a subclass of the AsyncTask class, as shown here:

private class DownloadImage extends AsyncTask<String, Void, Bitmap> {
    protected Bitmap  doInBackground(String... urls) {
    return getBitmapFromUrl(urls[0]);
    }
    protected void onPostExecute(Bitamp result) {
    ImageView img = (ImageView) findViewById(R.id.img);
    img.setImageBitmap(result);
    }
}

Now in the onCreate() method create a new instance of AsyncTask class and execute it:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    new DownloadImage().execute("http://upload.wikimedia.org/wikipedia/en/7/70/Example.png");
}
Marcin S.
  • 11,161
  • 6
  • 50
  • 63
2

this is because you are trying to access the internet from the ui thread (more info here) .

create a new thread (you can use an asyncTask if you wish, but any other thread creation method would suffice) in order to access the internet , and once the bitmap is ready , pass it to the ui thread if you wish to show it

also , for a nice sample of bitmap handling read this :

http://developer.android.com/training/displaying-bitmaps/index.html

android developer
  • 114,585
  • 152
  • 739
  • 1,270
0

Your void will crash when image size big 5 MG. Bitmap are stacking RAM so sample 20 images * 5 = 100 mb. When you re open activity another 100 mb spend your RAM and app will crash. You add follow lines your code;

                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Config.RGB_565;
                options.inSampleSize = 2;
                Bitmap myBitmap = BitmapFactory.decodeStream(input,rect,options);
Phd. Burak Öztürk
  • 1,727
  • 19
  • 29