0

我的应用程序可以使用 appcache 在线和离线运行。它还会在某一时刻在默认浏览器上打开一个链接。问题是当它离线加载时,链接到默认浏览器后无法重新打开应用程序。

这是我的代码:

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);
    }

}

这是 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

提前致谢。

4

1 回答 1

2

buildwv()初始化wvonRestoreInstanceState(). 但是,如果eolc()分支被采用,wv它仍然是未初始化的,即null在结束时,onCreate()因为buildwv()仅作为对对话框单击事件的响应而被调用。

看起来你应该wv无条件地初始化onCreate(),例如

setContentView(R.layout.activity_main);
wv = (WebView) findViewById(R.id.wv);
于 2013-09-30T10:35:28.860 回答