My App works on Gingerbread… Crash on ICS and HC

不问归期 提交于 2019-12-06 00:05:30

It is a bad idea to perform (potentially blocking) network operations on your app's main thread, which is what you are doing. Before Honeycomb (Android 3.0), it was just a bad idea. From Android 3.0 onwards, it is prohibited, and you receive this exception if you try to do so.

See http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

You need to farm out this network logic to a separate asynchronous thread. Or, look at a Handler. You're going to need to change your code architecture; no easy fix.

In Honeycomb networking is not allowed on the UI thread. The reason is that it slows down the user interface (UI).

Instead try to download your images in an background thread, the easiest way to implement this is using an AsyncTask.

Use it at your own risk:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll()
.build();
StrictMode.setThreadPolicy(policy);

Resource: http://developer.android.com/reference/android/os/StrictMode.ThreadPolicy.Builder.html

You can see the version of the OS, and execute a code depending of it.

For example:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD)

This is how I solve the problem:

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.TabHost.TabSpec;

public class f24 extends Activity {

    private ImageAdapter imageAdapter;

    private ArrayList<String> PhotoURLS = new ArrayList<String>();

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.f24);

        Button bhome = (Button) findViewById(R.id.homebutton);
        bhome.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                // TODO Auto-generated method stub
                startActivity(new Intent ("com.bozz.milaircraft.MENU"));
            }
        });


        TabHost th = (TabHost) findViewById(R.id.tabhost);
        th.setup();
        TabSpec specs = th.newTabSpec("tag1");
        specs.setContent(R.id.tab1);
        specs.setIndicator("BRIEFING");
        th.addTab(specs);
        specs = th.newTabSpec("tag2");
        specs.setContent(R.id.tab2);
        specs.setIndicator("DESIGN");
        th.addTab(specs);
        specs = th.newTabSpec("tag3");
        specs.setContent(R.id.tab3);
        specs.setIndicator("USERS");
        th.addTab(specs);
        specs = th.newTabSpec("tag4");
        specs.setContent(R.id.tab4);
        specs.setIndicator("GALLERY");
        th.addTab(specs);

        imageAdapter = new ImageAdapter(this);
        final ImageView imgView = (ImageView) findViewById(R.id.GalleryView);
        Gallery g = (Gallery) findViewById(R.id.Gallery);
        g.setAdapter(imageAdapter);
        g.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View v,
                    int position, long id) {
                imgView.setImageDrawable(LoadImageFromURL(PhotoURLS
                        .get(position)));
                imgView.setScaleType(ImageView.ScaleType.FIT_CENTER);
            }
        });

        // replace this code to set your image urls in list
        PhotoURLS.add("http://www.medicinarozzano.it/images/milair/f4_1.jpg");
        PhotoURLS.add("http://www.medicinarozzano.it/images/milair/f4_1.jpg");

        new AddImageTask().execute();

    }

    class AddImageTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... unused) {
            for (String url : PhotoURLS) {
                String filename = url.substring(url.lastIndexOf("/") + 1,
                        url.length());
                filename = "th_" + filename;
                String thumburl = url.substring(0, url.lastIndexOf("/") + 1);
                imageAdapter.addItem(LoadThumbnailFromURL(thumburl + filename));
                publishProgress();
                //SystemClock.sleep(200);
            }

            return (null);
        }

        @Override
        protected void onProgressUpdate(Void... unused) {
            imageAdapter.notifyDataSetChanged();
        }

        @Override
        protected void onPostExecute(Void unused) {
        }
    }

    private Drawable LoadThumbnailFromURL(String url) {
        try {
            URLConnection connection = new URL(url).openConnection();
            String contentType = connection.getHeaderField("Content-Type");
            boolean isImage = contentType.startsWith("image/");
            if(isImage){
                HttpGet httpRequest = new HttpGet(url);
                HttpClient httpclient = new DefaultHttpClient();
                HttpResponse response = (HttpResponse) httpclient
                        .execute(httpRequest);
                HttpEntity entity = response.getEntity();
                BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(entity);

                InputStream is = bufferedHttpEntity.getContent();
                Drawable d = Drawable.createFromStream(is, "src Name");
                return d;
            } else {
                Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.no_image);
                Drawable d = new BitmapDrawable(b);
                return d;
            }
        } catch (Exception e) {
            Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG)
                    .show();
            Log.e(e.getClass().getName(), e.getMessage(), e);
            return null;
        }
    }

    private Drawable LoadImageFromURL(String url) {
        try {
            URLConnection connection = new URL(url).openConnection();
            String contentType = connection.getHeaderField("Content-Type");
            boolean isImage = contentType.startsWith("image/");
            if(isImage){
                HttpGet httpRequest = new HttpGet(url);
                HttpClient httpclient = new DefaultHttpClient();
                HttpResponse response = (HttpResponse) httpclient
                        .execute(httpRequest);
                HttpEntity entity = response.getEntity();
                BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(
                        entity);
                InputStream is = bufferedHttpEntity.getContent();

                // Decode image size
                BitmapFactory.Options o = new BitmapFactory.Options();
                o.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(is, null, o);

                // The new size we want to scale to
                final int REQUIRED_SIZE = 150;

                // Find the correct scale value. It should be the power of 2.
                int width_tmp = o.outWidth, height_tmp = o.outHeight;
                int scale = 1;
                while (true) {
                    if (width_tmp / 2 < REQUIRED_SIZE
                            || height_tmp / 2 < REQUIRED_SIZE)
                        break;
                    width_tmp /= 2;
                    height_tmp /= 2;
                    scale *= 2;
                }

                // Decode with inSampleSize
                is = bufferedHttpEntity.getContent();
                BitmapFactory.Options o2 = new BitmapFactory.Options();
                o2.inSampleSize = scale;
                Bitmap b = BitmapFactory.decodeStream(is, null, o2);
                Drawable d = new BitmapDrawable(b);
                return d;
            } else {
                Bitmap b = BitmapFactory.decodeResource(getResources(), R.drawable.no_image);
                Drawable d = new BitmapDrawable(b);
                return d;
            }
        } catch (Exception e) {
            Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_LONG)
                    .show();
            Log.e(e.getClass().getName(), e.getMessage(), e);
            return null;
        }
    }

    public class ImageAdapter extends BaseAdapter {
        int mGalleryItemBackground;
        private Context mContext;

        ArrayList<Drawable> drawablesFromUrl = new ArrayList<Drawable>();

        public ImageAdapter(Context c) {
            mContext = c;
            TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
            mGalleryItemBackground = a.getResourceId(
                    R.styleable.Gallery1_android_galleryItemBackground, 0);
            a.recycle();
        }

        public void addItem(Drawable item) {
            drawablesFromUrl.add(item);
        }

        public int getCount() {
            return drawablesFromUrl.size();
        }

        public Drawable getItem(int position) {
            return drawablesFromUrl.get(position);
        }

        public long getItemId(int position) {
            return position;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView i = new ImageView(mContext);

            i.setImageDrawable(drawablesFromUrl.get(position));
            i.setLayoutParams(new Gallery.LayoutParams(150, 120));
            i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
            i.setBackgroundResource(mGalleryItemBackground);

            return i;
        }
    }

}

But now I have another problem:

If i don not declare any SDK on Android Manifest, the app works perfectly on both gingerbread and HC, and ICS. However, if i declare a minimum SDK greater than 1 or TargetSDK, the app works fine on gingerbread but not on HC and ISC. When i click on an image in the gallery nothing appears on the image viewer. Yet, a toast error pops up.

Also, if there is no internet connection the app crashes.

Best regards Tiberio Bozotti

EDIT: i could remove the SDK but on honeycomb it is not clear. Meaning that the layout is not compatible.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!