java.lang.NullPointerException: Try invoking the virtual method 'android.content.res.Resources android.content.Context.getResources ()

advertisements

I'm pulling a html page from the web. The page contains images and I load the images with UILImageGetter.

The problem is that if the page just begins to load and I rotate the device multiple times the app crashes with an NPE.

UILImageGetter

public class UILImageGetter implements Html.ImageGetter{
    Context c;
    TextView container;
    UrlImageDownloader urlDrawable;

    public UILImageGetter(View textView, Context context) {
        this.c = context;
        this.container = (TextView) textView;
    }

    @Override
    public Drawable getDrawable(String source) {
        urlDrawable = new UrlImageDownloader(c.getResources(), source);
        if (Build.VERSION.SDK_INT >= 21) {
        urlDrawable.mDrawable = c.getResources().getDrawable(R.drawable.default_thumb,null);
        } else {
            urlDrawable.mDrawable = c.getResources().getDrawable(R.drawable.default_thumb);
        }
        ImageLoader.getInstance().loadImage(source, new SimpleListener(urlDrawable));
        return urlDrawable;
    }

    private class SimpleListener extends SimpleImageLoadingListener {
        UrlImageDownloader mUrlImageDownloader;

        public SimpleListener(UrlImageDownloader downloader) {
            super();
            mUrlImageDownloader= downloader;
        }

        @Override
        public void onLoadingStarted(String imageUri, View view) {
            Log.d("DEBUG", "onLoadingStarted called");
            //spinner.setVisibility(View.VISIBLE);

        }

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
            //spinner.setVisibility(View.GONE);

            int width = loadedImage.getWidth();
            int height = loadedImage.getHeight();

            int newWidth = width;
            int newHeight = height;

            if (width > container.getWidth()) {
                newWidth = container.getWidth();
                newHeight = (newWidth * height) / width;
            }

            if (view != null) {
                container.getLayoutParams().width = newWidth;
                container.getLayoutParams().height = newHeight;
            }

            Drawable result = new BitmapDrawable(c.getResources(), loadedImage);
            result.setBounds(0, 0, newWidth, newHeight);

            mUrlImageDownloader.setBounds(1, 1, newWidth, newHeight);
            mUrlImageDownloader.mDrawable = result;
            container.invalidate();

            container.setText(container.getText());

        }

        @Override
        public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
            String message = null;
            switch (failReason.getType()) {
                case IO_ERROR:
                    message = "Input/Output error";
                    break;
                case DECODING_ERROR:
                    message = "Image can't be decoded";
                    break;
                case NETWORK_DENIED:
                    message = "Downloads are denied";
                    break;
                case OUT_OF_MEMORY:
                    message = "Out Of Memory error";
                    break;
                case UNKNOWN:
                    message = "Unknown error";
                    break;
            }
            Toast.makeText(view.getContext(), message, Toast.LENGTH_SHORT).show();
            //spinner.setVisibility(View.GONE);
        }
    }

    private class UrlImageDownloader extends BitmapDrawable {
        public  Drawable mDrawable;

        public UrlImageDownloader(Resources resources, String filepath) {
            super(resources, filepath);
            mDrawable = new BitmapDrawable(resources, filepath);
        }

        @Override
        public void draw(Canvas canvas) {
            if (mDrawable != null) {
                mDrawable.draw(canvas);
            }
        }
    }
}

DetailsFragment

public class DetailsFragment extends Fragment implements ObservableScrollViewCallbacks{

    private AlertDialog internetDialog;
    private AlertDialog sthWrongAlert;
    private String url;

    private String birdData;

    private final String TAG = "DetailsFragment";
    protected com.nostra13.universalimageloader.core.ImageLoader mImageLoader;

    TextView birdContent;
    public DetailsFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        url = getArguments().getString("bird_link");

        // Inflate the layout for this fragment
        view =  inflater.inflate(R.layout.fragment_details, container, false);

        showDialog();
        sthWrongDialog();

        gadContent = (TextView) view.findViewById(R.id.gad_content);

        DisplayImageOptions defaultoptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getActivity())
                .defaultDisplayImageOptions(defaultoptions)
                .writeDebugLogs()
                .build();

        mImageLoader = com.nostra13.universalimageloader.core.ImageLoader.getInstance();
        mImageLoader.init(config);

        if (savedInstanceState != null) {
            birdData = savedInstanceState.getString("birdData");
            if (birdData != null) {
                parseHtml(birdData);
            }
            } else if (NetworkCheck.isAvailableAndConnected(getActivity())){
                    loadBird();
                }
            }
        } else {
            if (NetworkCheck.isAvailableAndConnected(getActivity())) {
                    loadGad();
                }
            } else {
                internetDialog.show();
            }
        }
        return view;
    }

    public interface OnLinkClickedListener {
        public void OnLinkClicked (String link);
    }

    private static OnLinkClickedListener sLinkCallbacks = new OnLinkClickedListener() {
        @Override
        public void OnLinkClicked(String link) {

        }
    };

    private void showDialog() {
        internetDialog = new AlertDialog.Builder(getActivity())
                // The usuals
                .create();
    }

    private void sthWrongDialog() {
        sthWrongAlert = new AlertDialog.Builder(getActivity())
                // The usuals
                .create();
    }

    private void loadBird() {
        Log.d(TAG, "loadBird called");

        final ProgressBar progressBar;
        progressBar = (ProgressBar) view.findViewById(R.id.progress_circle);
        progressBar.setVisibility(View.VISIBLE);

//        String news_id = getIntent().getStringExtra("BirdId");
        Log.d(TAG, "You clicked bird id " + url);

        StringRequest stringRequest = new StringRequest(url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //Log.d("Debug", response.toString());
                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                        parseHtml(response);
                        birdData = response;

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        VolleyLog.d(TAG, "Error: " + error.getMessage());

                        if (progressBar != null) {
                            progressBar.setVisibility(View.GONE);
                        }
                        if (sthWrongAlert != null) {
                            sthWrongAlert.show();
                        }

                    }
                });

        //Creating requestqueue
        RequestQueue requestQueue = Volley.newRequestQueue(getActivity());

        //Adding request queue
        requestQueue.add(stringRequest);
    }

    private void parseHtml(String response) {
        Log.d(TAG, "parsinghtml");
        Document document = Jsoup.parse(response);
        bird_content = document.select("div.entry-content").first().html();
        setTextViewHTML(birdContent, bird_content);
    protected void makeLinkClickable(SpannableStringBuilder strBuilder, final URLSpan span)
    {
        int start = strBuilder.getSpanStart(span);
        int end = strBuilder.getSpanEnd(span);
        int flags = strBuilder.getSpanFlags(span);
        ClickableSpan clickable = new ClickableSpan() {
            public void onClick(View view) {
                Log.e(TAG, "on click" + span.getURL());
            }
        };
        strBuilder.setSpan(clickable, start, end, flags);
        strBuilder.removeSpan(span);
    }

    protected void setTextViewHTML(TextView text, String html) {
        CharSequence sequence = Html.fromHtml(html, new UILImageGetter(birdContent, getActivity()), null);
        SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
        URLSpan[] urls = strBuilder.getSpans(0, sequence.length(), URLSpan.class);
        for(URLSpan span : urls) {
            makeLinkClickable(strBuilder, span);
        }
        text.setText(strBuilder);
        text.setMovementMethod(LinkMovementMethod.getInstance());
    }

       @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (birdData != null) {
            outState.putString("birdData", birdData);
        }

        if (internetDialog != null) {
            outState.putBundle("internetDialog", internetDialog.onSaveInstanceState());
        }
        if (sthWrongAlert != null) {
            outState.putBundle("sthWrongAlert", sthWrongAlert.onSaveInstanceState());
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (savedInstanceState != null) {
            if (internetDialog != null) {
                internetDialog.onRestoreInstanceState(savedInstanceState.getBundle("internetDialog"));
            }
            if (sthWrongAlert != null) {
                sthWrongAlert.onRestoreInstanceState(savedInstanceState.getBundle("sthWrongAlert"));

            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy called");
        if (mImageLoader.isInited()) {
            mImageLoader.destroy();
        }

        if (internetDialog != null){
            internetDialog.dismiss();
            internetDialog = null;
        }
        if (sthWrongAlert != null) {
            sthWrongAlert.dismiss();
            sthWrongAlert = null;
        }
    }

}

StackTrace

05-19 13:37:14.936 12213-12213/com.pexample.birds E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: com.pexample.birds, PID: 12213
                                                                     java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
                                                                         at com.pexample.birds.UILImageGetter.getDrawable(UILImageGetter.java:39)
                                                                         at android.text.HtmlToSpannedConverter.startImg(Html.java:634)
                                                                         at android.text.HtmlToSpannedConverter.handleStartTag(Html.java:520)
                                                                         at android.text.HtmlToSpannedConverter.startElement(Html.java:761)
                                                                         at org.ccil.cowan.tagsoup.Parser.push(Parser.java:794)
                                                                         at org.ccil.cowan.tagsoup.Parser.rectify(Parser.java:1061)
                                                                         at org.ccil.cowan.tagsoup.Parser.stagc(Parser.java:1016)
                                                                         at org.ccil.cowan.tagsoup.HTMLScanner.scan(HTMLScanner.java:624)
                                                                         at org.ccil.cowan.tagsoup.Parser.parse(Parser.java:449)
                                                                         at android.text.HtmlToSpannedConverter.convert(Html.java:442)
                                                                         at android.text.Html.fromHtml(Html.java:136)
                                                                         at com.pexample.birds.DetailsFragment.setTextViewHTML(DetailsFragment.java:400)
                                                                         at com.pexample.birds.DetailsFragment.parseHtml(DetailsFragment.java:350)
                                                                         at com.pexample.birds.DetailsFragment.access$500(DetailsFragment.java:48)
                                                                         at com.pexample.birds.DetailsFragment$6.onResponse(DetailsFragment.java:291)
                                                                         at com.pexample.birds.DetailsFragment$6.onResponse(DetailsFragment.java:284)
                                                                         at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
                                                                         at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
                                                                         at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
                                                                         at android.os.Handler.handleCallback(Handler.java:739)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                         at android.os.Looper.loop(Looper.java:135)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5910)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:372)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1405)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1200)

From the stacktrace, line 39 is urlDrawable = new UrlImageDownloader(c.getResources(), source); in UILImageGetter and line 400 corrsponds to line CharSequence sequence = Html.fromHtml(html, new UILImageGetter(birdContent, getActivity()), null); in DetailsFragment.

Please, how do I fix this?

Please this not a duplicate of this question. I know what a NPE and what causes it and maybe I am wrong but I also know that I will have to check if the resource is null before line urlDrawable = new UrlImageDownloader(c.getResources(), source); but I just don't know how to do that. I am lost here, please help me.


EDIT

onCreate of hosting Activity

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post);

        getWindow().getDecorView().setBackgroundColor(Color.WHITE);

        String bird_id = getIntent().getStringExtra("BirdId");
        Log.d(TAG,  bird_id);

        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        if (savedInstanceState == null) {
            Bundle bundle = new Bundle();
            Fragment fragment;

            fragment = new DetailsFragment();
            bundle.putString("bird_link", bird_id);
            fragment.setArguments(bundle);

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            ft.setCustomAnimations(android.R.anim.slide_out_right, android.R.anim.slide_in_left, android.R.anim.slide_out_right, android.R.anim.slide_in_left);
            ft.add(R.id.post_frame, fragment);
            ft.commit();
        }

        if (savedInstanceState != null) {
            mContent = getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
        }

    }


When you are transfer from portrait to landscape then your activity will restart. When you first time start then your context not null but when you are change the screen then your context will null and your app will crash.I suggest that just set screen orientations Portrait in your manifest file. like this

<activity
        android:name="..."
        android:label="@string/app_name"
        android:screenOrientation="portrait"/>