-1

I am working on an Android App where I am trying to decode InputStream to Bitmap .

Bitmap bmp = BitmapFactory.decodeStream(s);

Above line inside QBContent.downloadFileTask(...) throwing NetworkOnMainThread exception.

Here is the reference code :

getView() of ChatAdapter

      @Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    QBChatMessage chatMessage = getItem(position);
    LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    int type = getItemViewType(position);
    if (convertView == null) {
        convertView = vi.inflate(R.layout.list_item_image, parent, false);
        holder = createViewHolder(convertView);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    QBUser currentUser = ChatService.getInstance().getCurrentUser();
    boolean isOutgoing = chatMessage.getSenderId() == null || chatMessage.getSenderId().equals(currentUser.getId());
    setAlignment(holder, isOutgoing);

    Collection<QBAttachment> attachments = chatMessage.getAttachments();
    //attachments.
    if (attachments != null && attachments.size() > 0) {

        String imageid = "";
        for (QBAttachment attachment : attachments) {
            imageid = attachment.getId();
        }

        final int imageid1 = Integer.parseInt(imageid);

        QBContent.downloadFileTask(imageid1, new QBEntityCallbackImpl<InputStream>() {
            @Override
            public void onSuccess(InputStream inputS, Bundle params) {

                if (inputS != null) {
                    Bitmap bmp = BitmapFactory.decodeStream(inputS);
                    Drawable d = new BitmapDrawable(context.getResources(), bmp);
                    if (holder.image_attachment != null)
                        holder.image_attachment.setImageDrawable(d);
                }
            }
            @Override
            public void onError(List<String> errors) {
                Log.d("Image Download Error : ", errors.toString());
            }
        }, new QBProgressCallback() {
            @Override
            public void onProgressUpdate(int progress) {
            }
        });
    } 
    return convertView;
}

What wrong I am doing here ? Help me please .

Soft Kaka
  • 1,582
  • 2
  • 14
  • 39
  • post your complete log – Vivek Mishra Jan 05 '16 at 06:34
  • @VivekMishra I included the logs plz check it – Soft Kaka Jan 05 '16 at 07:06
  • `at androidclient.com.qbchatsample.ui.adapters.ChatAdapter$BackgroundOperation.onPostExecute(ChatAdapter.java:293)` What is at this line?? – Vivek Mishra Jan 05 '16 at 07:10
  • @Vivek Mishra Bitmap bmp = BitmapFactory.decodeStream(s); inside onPostExcecute. – Soft Kaka Jan 05 '16 at 07:12
  • are you having this asynctask inside adapter?? – Vivek Mishra Jan 05 '16 at 07:12
  • then I think indirectly you are calling network on main thread as adapters are used to update ui and they run on main thread – Vivek Mishra Jan 05 '16 at 07:14
  • So that line should be in doInBackground. Please show how you call your AsyncTask. – greenapps Jan 05 '16 at 07:18
  • I have included more details ,Plz check it . – Soft Kaka Jan 05 '16 at 07:26
  • @greenapps I have edited . – Soft Kaka Jan 05 '16 at 07:34
  • Here I want to mention that onSucess() of QBContent.downloadFileTask() executes on UI thread . – Soft Kaka Jan 05 '16 at 07:42
  • 1
    You have crazy code. You are creating a handler in the doInBackground of an asynctask and let it act on a Runnable. Why would you? Remove the AsyncTask and create instead the handler and the runnable directly. Place the bitmap in onSucces().Or keep the Asynctask and remove the handler and the runnable. – greenapps Jan 05 '16 at 08:51
  • @greenapps Great ! I am working on the same part of the code . Initially I didn't put Handler and Runnable but it was giving error "Can't create handler inside thead that has not called Looper.prepare()" . So I put Hander and runnable it removed the issue . Can you plz suggest me right way to do it . – Soft Kaka Jan 05 '16 at 09:28
  • I already suggested a little how to do this. So remove your async task. Instead of calling an asynctask you call `QBContent.downloadFileTask(....)` directly. Or do it as Jigar Shekh suggested. – greenapps Jan 05 '16 at 09:37
  • I have put QBContent.downloadFileTask(....) outside the AsyncTask , but I am getting exception at line Bitmap bmp = BitmapFactory.decodeStream(s); – Soft Kaka Jan 05 '16 at 09:54
  • NetworkonMainThreadException . – Soft Kaka Jan 05 '16 at 09:54
  • @greenapps Thanks man for your help . I got the answer now . I have posted it as answer . – Soft Kaka Jan 05 '16 at 11:11

4 Answers4

2

Try this

private class SampleAsync extends AsyncTask<Void, Void, Bitmap> {

    @Override
    protected Bitmap doInBackground(Void... params) {
        // your background code fetch InputStream
        InputStream s = //your inputstream ;
        Bitmap bmp = BitmapFactory.decodeStream(s);
        return bmp;
    }

    @Override
    protected void onPostExecute(Bitmap bmp) {
        super.onPostExecute(bmp);
        if(bmp != null){
            Drawable d = new BitmapDrawable(context.getResources(), bmp);
            if(holder.image_attachment != null)
                holder.image_attachment.setImageDrawable(d);
        }
    }
}
Jigar Shekh
  • 2,780
  • 5
  • 28
  • 52
  • I did the same ,but the line Bitmap bmp = BitmapFactory.decodeStream(s); inside doInBackground() returned the NetworkOnMainThread Exception . – Soft Kaka Jan 05 '16 at 06:45
  • 1
    Please check this link. http://stackoverflow.com/questions/12615607/android-os-networkonmainthreadexception – Jigar Shekh Jan 05 '16 at 07:00
  • `I did the same` ??? Your code is completely different with that handler and other stuff. – greenapps Jan 05 '16 at 09:06
0

Do the same inside the doInbackground method and do the actions inside a UI thread

Sreyas
  • 610
  • 1
  • 7
  • 22
0

You are indirectly you are calling network on main thread as adapters are used to update ui and they run on main thread. To solve it either move complete code with adapter to another asyncTask or remove your asynctask call from adapter.

Vivek Mishra
  • 5,494
  • 7
  • 44
  • 77
0

Finally I got the answer .

1 . Removed the AsyncTask and called QBContent.downloadFileTask(...) directly.

2 . Modified QBContent.downloadFileTask(...) . Here I have decoded InputStream to BitMap in a Background thread , Previously I was doing it in UI thread .

QBContent.downloadFileTask(imageid1, new QBEntityCallbackImpl<InputStream>() {
            @Override
            public void onSuccess(final InputStream inputS, Bundle params) {

                if (inputS != null) {
                    new Thread() {
                        public void run() {
                            final Bitmap bmp = BitmapFactory.decodeStream(inputS);
                            try {
                                context.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Drawable d = new BitmapDrawable(context.getResources(), bmp);
                                        if (holder.image_attachment != null)
                                            holder.image_attachment.setImageDrawable(d);
                                    }
                                });
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }.start();
                }

            }

            @Override
            public void onError(List<String> errors) {
                Log.d("Image Download Error : ", errors.toString());

            }
        }, new QBProgressCallback() {
            @Override
            public void onProgressUpdate(int progress) {

            }
        });
Soft Kaka
  • 1,582
  • 2
  • 14
  • 39
  • Very bad solution. Start programming in a normal way and remove that StrintMode statement. – greenapps Jan 05 '16 at 11:14
  • @greenapps then help me plz , I dont know any other way . – Soft Kaka Jan 05 '16 at 11:16
  • What happens if you remove the StrintMode call? – greenapps Jan 05 '16 at 11:17
  • It is giving NetworkonMainThreadException while decoding inputstream to Bitmap . – Soft Kaka Jan 05 '16 at 11:18
  • Please edit your post so we can see the code you use now. Remove all irrelevant code. Or maybe add another code block to show your new code. – greenapps Jan 05 '16 at 11:20
  • 1
    What is this `QBContent.downloadFileTask()` ? You did not post the code. Is it originally for a Java application? It seems not suitable for Android as onSucces() has an InputStream parameter. onSuccess() will be executed on the main thread so you cannot read from that -network- stream in onSuccess to begin with. – greenapps Jan 05 '16 at 11:58
  • @greenapps I have removed StrictMode . So I think I have found a good solution now . Plz remove your first comment , very bad solution :) – Soft Kaka Jan 05 '16 at 12:07
  • `Modified QBContent.downloadFileTask`. No you did not. You added a thread to your code in onSucces() to read from the input stream. So you only start the download in onSucces. Strange and wrong. Much better would be to do the download in the `QBContent.downloadFileTask`it self and change onSucces to have a Bitmap parameter. There should be only succes after downloading the file and having a bitmap. – greenapps Jan 05 '16 at 12:10
  • @greenapps Can you please post your comment as an answer , and a right code snippet for QBContent.downloadFileTask(...) so that I can understand more clearly . – Soft Kaka Jan 05 '16 at 12:14
  • First please explain why you use QBContent.downloadFileTask(...). It looks not suitable for android. If you only need to download an image from the internet and convert to a Bitmap you could much better use an AsyncTask and HttpUrlConnection. – greenapps Jan 05 '16 at 12:18
  • @greenapps See , I am working on a chat application , Here I am trying to send attachment ( image ), for this I am using QuickBlox Sdk . So here I am using QuickBlox api to download image from QuickBlox Server . And QBContent.downloadFileTask() is the part of QuickBlox Api . Here I am using imageid to download image . – Soft Kaka Jan 05 '16 at 12:25
  • Is that QB API for Android? – greenapps Jan 05 '16 at 12:26
  • Since I am using imageid So I can't use AsyncTask and HttpUrlConnection . – Soft Kaka Jan 05 '16 at 12:27
  • Here is the link : http://quickblox.com/developers/SimpleSample-content-android#Download_file – Soft Kaka Jan 05 '16 at 12:28
  • I cannot comment on that as you did not post the code for `downloadFileTask()` so we cannot see what url is used. Tell us the url and if GET or POST is used. – greenapps Jan 05 '16 at 12:28
  • It's the QuickBlox api method downloadFileTask() . So I need to debug code . I am doing it .Plz wait . – Soft Kaka Jan 05 '16 at 12:31
  • `SimpleSample-content-android`. Well you saw that it does not work in Android whithout using a thread to read from the inputstream. I wonder what they mean with `success`. A succesfull connection? – greenapps Jan 05 '16 at 12:31
  • Yes , this is a misleading doc. I am really frustated . – Soft Kaka Jan 05 '16 at 12:35
  • It takes file id only , I have seen no url , no GET and POST . – Soft Kaka Jan 05 '16 at 12:38
  • Ok it takes a file id. But what is done with that id? And how is an input stream opened and onSuccess called with that input stream as parameter? – greenapps Jan 05 '16 at 12:40
  • I have tried for this exercise earlier for the same problem , But it is very confusing . – Soft Kaka Jan 05 '16 at 12:42
  • Well ok. Meanwhile i think that you found a workable solution that keeps as close as possible to QuickBlox. – greenapps Jan 05 '16 at 12:45
  • Yes , Thanks for your amazing help . – Soft Kaka Jan 05 '16 at 12:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/99817/discussion-between-android-dev-and-greenapps). – Soft Kaka Jan 05 '16 at 12:51