Lendl Leyba
Lendl Leyba

Reputation: 2287

Android linking crashes the app

My app can run online and offline using appcache. It also opens a link on the default browser at one point. Problem is that when it is loading offline, it could't reopen the app after linking to the default broswer.

Here is my code:

public class MainActivity extends Activity
{

    private WebView wv;
    private ProgressBar progress;
    private static String mycaturl="*url*";
    private static String helpurl="*url*";
    private static String fbackurl="*url*";

    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
        StrictMode.setThreadPolicy(policy);
        if (reachable(this))
        {
            buildwv( savedInstanceState, WebSettings.LOAD_DEFAULT, mycaturl );
        }
        else
        {
            eolc( savedInstanceState );
        }
    }

    @SuppressLint({ "SetJavaScriptEnabled" })
    public void buildwv(Bundle sis, int load, String url)
    {
        if(reachable(this))
        {
            this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
        }
        else
        {
            this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
        }
        setContentView(R.layout.activity_main);
        progress=(ProgressBar) findViewById(R.id.progress);
        wv=(WebView) findViewById(R.id.wv);
        wv.setWebViewClient( new wvc() );
        wv.setHorizontalScrollBarEnabled(false);
        WebSettings ws = wv.getSettings();
        ws.setAppCacheMaxSize( 100 * 1024 * 1024 ); // 100MB
        ws.setAppCachePath( this.getCacheDir().getAbsolutePath() );
        ws.setAllowFileAccess( true );
        ws.setAppCacheEnabled( true );
        ws.setJavaScriptEnabled( true );
        ws.setCacheMode(load);
        if(sis==null)
        { wv.loadUrl(url); }
    }

    public void eolc(final Bundle sis)
    {
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
        AlertDialog.Builder ad = new AlertDialog.Builder( MainActivity.this );
        ad.setTitle("Unreachable Host");
        ad.setMessage("Host is unreachable. Load from cache or exit.");
        ad.setIcon(R.drawable.tick);
        ad.setCancelable(false);
        ad.setPositiveButton( "Load from Cache", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog,int which)
            {
                buildwv( sis, WebSettings.LOAD_CACHE_ELSE_NETWORK, mycaturl );
            }
        });
        ad.setNeutralButton( "Help", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                buildwv( sis, WebSettings.LOAD_CACHE_ELSE_NETWORK, helpurl );
            }
        });

        ad.setNegativeButton( "Exit", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                finish();
            }
        });
        ad.create();
        ad.show();
    }

    public void alertprep(String set)
    {
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

        if( set=="def")
        {
            String a = "Connection Lost";
            String b = "Connection to host was lost. Restart and load cache or exit.";
            alert(a,b);
        }
        else if( set=="cac" )
        {
            String a = "Page Not Cached";
            String b = "Page you're trying to view is not yet cached. Please visit help to learn how to cache.";
            alert(a,b);
        }
    }

    public void alert(String a,String b)
    {
        AlertDialog.Builder ad = new AlertDialog.Builder( MainActivity.this );
        ad.setTitle(a);
        ad.setMessage(b);
        ad.setIcon(R.drawable.tick);
        ad.setCancelable(false);
        ad.setPositiveButton( "Restart", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog,int which)
            {
                Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
                startActivity(i);
            }
        });
        ad.setNeutralButton( "Help", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                wv.stopLoading();
                wv.loadUrl( helpurl );
            }
        });
        ad.setNegativeButton( "Exit", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                finish();
            }
        });
        ad.create();
        ad.show();
    }

    private class wvc extends WebViewClient
    {
        public void onPageStarted(WebView view, String url, Bitmap favicon)
        {
            super.onPageStarted(view, url, favicon);
            progress.setVisibility(View.VISIBLE);
            if (url.contains(mycaturl))
            {
                WebSettings ws = wv.getSettings();
                if ( !reachable(getApplicationContext()) )
                {
                    if ( ws.getCacheMode() == WebSettings.LOAD_DEFAULT )
                    {
                        alertprep("def");
                    }
                }
            }
        }

        @Override
        public void onPageFinished(WebView view, String url) 
        {
            super.onPageFinished(view, url);
            progress.setVisibility(View.GONE);
        }

        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
          {
              super.onReceivedError(view, errorCode, description, failingUrl);
              wv.loadUrl(helpurl);
              WebSettings ws = wv.getSettings();
              if ( ws.getCacheMode() == WebSettings.LOAD_DEFAULT )
              {
                  alertprep("def");
              }
              else
              {
                  alertprep("cac");
              }
          }

          public boolean shouldOverrideUrlLoading(WebView view, String url)
          {           
              if (url != null && url.contains("dgcrfdbck"))
              {
                  jumptofback();
                  return true;
              } else {
                  return false;
              }
          }
      }

    public void jumptofback()
    {
        wv.getContext().startActivity(
                new Intent(Intent.ACTION_VIEW, Uri.parse(fbackurl)));
    }

    public static boolean reachable(Context context) 
    {
        final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo netInfo = connMgr.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) 
        {
            try 
            {
                URL url = new URL(mycaturl);
                HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
                urlc.setConnectTimeout(5000);
                urlc.connect();
                if (urlc.getResponseCode() == 200)
                {   return true;    } else {    return false;   }
            }
            catch (IOException e)
            {   return false;   }
        }
        else
        {   return false;   }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void onBackPressed ()
    {
        if (wv.isFocused() && wv.canGoBack())
        {   wv.goBack();    }   else {  finish();   }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case R.id.item1:
                wv.loadUrl( helpurl );
                break;
            case R.id.item2:
                jumptofback();
                break;
            case R.id.item3:
                String currurl=wv.getUrl();
                wv.loadUrl(currurl);   
                break;
            case R.id.item4:
                Intent i = getBaseContext().getPackageManager()
                 .getLaunchIntentForPackage( getBaseContext().getPackageName() );
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(i);
                break;
            case R.id.item5:
                finish();
                break;
            default:
                break;
        }
        return true;
    } 

    @Override
    protected void onSaveInstanceState(Bundle outState )
    {
        super.onSaveInstanceState(outState);
        wv.saveState(outState);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState)
    {
        super.onSaveInstanceState(savedInstanceState);
        wv.restoreState(savedInstanceState);
    }

}

Here's the error part in the logcat:

09-30 18:25:04.375: D/AndroidRuntime(15930): Shutting down VM
09-30 18:25:04.375: W/dalvikvm(15930): threadid=1: thread exiting with uncaught exception (group=0x41b352a0)
09-30 18:25:04.380: E/AndroidRuntime(15930): FATAL EXCEPTION: main
09-30 18:25:04.380: E/AndroidRuntime(15930): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.msiecsapps.mycatlog/com.msiecsapps.mycatlog.MainActivity}: java.lang.NullPointerException
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.ActivityThread.access$600(ActivityThread.java:140)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.os.Handler.dispatchMessage(Handler.java:99)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.os.Looper.loop(Looper.java:137)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.ActivityThread.main(ActivityThread.java:4898)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at java.lang.reflect.Method.invokeNative(Native Method)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at java.lang.reflect.Method.invoke(Method.java:511)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at dalvik.system.NativeStart.main(Native Method)
09-30 18:25:04.380: E/AndroidRuntime(15930): Caused by: java.lang.NullPointerException
09-30 18:25:04.380: E/AndroidRuntime(15930):    at com.msiecsapps.mycatlog.MainActivity.onRestoreInstanceState(MainActivity.java:305)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.Activity.performRestoreInstanceState(Activity.java:944)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1134)
09-30 18:25:04.380: E/AndroidRuntime(15930):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
09-30 18:25:04.380: E/AndroidRuntime(15930):    ... 11 more

Thanks in advance.

Upvotes: 0

Views: 155

Answers (1)

laalto
laalto

Reputation: 152817

Your buildwv() initialized the wv variable that is used in onRestoreInstanceState(). However, if the eolc() branch is taken, wv is still uninitialized i.e. null at the end of onCreate() since buildwv() is only called as a response to a dialog click event.

Looks like you should initialize wv unconditionally in onCreate(), e.g.

setContentView(R.layout.activity_main);
wv = (WebView) findViewById(R.id.wv);

Upvotes: 2

Related Questions