6

我已经嵌入科尔多瓦WebvView作为我的项目组件,除了一件事情,一切正常;当按下后退按钮时,我在LogCat上看到一个错误,表示“Receiver Not Registered!”我不认为我已经注册了一个接收器。 GitHub here上也有一个示例项目。当我运行这个应用程序时,我也会遇到同样的错误。嵌入科尔多瓦WebView,接收器未注册

我想要做的是,将Cordova WebView嵌入到我的Android项目中并运行一些JavaScript函数。

这是我的主要活动;

public class MainNativeViewController extends FragmentActivity implements CordovaInterface, 
    JavaScriptListener { 

FragmentTransaction transaction; 
RelativeLayout childBrowser; 
RelativeLayout dialogBox; 
RelativeLayout emailComposer; 

private ExecutorService threadPool; 

CordovaWebViewFragment cordovaWebViewFragment; 

public CordovaWebView cordovaWebView; 

public LayoutInflater inflater; 
CordovaPlugin mActivityResultCallback; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    // TODO Auto-generated method stub 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.fragment_container); 

    overridePendingTransition(R.anim.fade_in, R.anim.fade_out); 

    threadPool = Executors.newCachedThreadPool(); 

    cordovaWebView = SingleTonCordovaWebView.getCordovaWebView(this); 
    cordovaWebView.loadUrl("file:///android_asset/www/invoke_native_view.html"); 

    FragmentManager manager = getSupportFragmentManager(); 

    ListFragment listFragment = new ListFragment(); 

    manager.beginTransaction().add(R.id.fragment_container, listFragment).commit(); 
} 

@Override 
public void showFragment(String fragmentName) { 

    /* 
    * This method is used to create and replace a fragment to the 
    * container. according to name passed through here. 
    */ 

    transaction = getSupportFragmentManager().beginTransaction(); 
    transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, 
      R.anim.slide_in_left, R.anim.slide_out_right); 

    if (fragmentName.equals("error")) { 
     DialogCreator dialog = new DialogCreator(this); 
     dialog.createDialog("Error !", "Fragment Name is wrong,", "Check fragment name", false); 
    } else { 
     // fragment name is ignored for different cases, it will be used for 
     // further proporties. 
     // Just checking out the error in the case its not right parameter. 

     NativeViewTestFragment testFragment = new NativeViewTestFragment(fragmentName); 

     transaction.replace(R.id.fragment_container, testFragment); 
     transaction.addToBackStack(null); 
     transaction.commit(); 
    } 
} 

@Override 
protected void onNewIntent(final Intent intent) { 
    super.onNewIntent(intent); 

    // Forward to plugins 
    if ((this.cordovaWebView != null) && (this.cordovaWebView.pluginManager != null)) { 
     this.cordovaWebView.pluginManager.onNewIntent(intent); 
    } 
} 

@Override 
public void cancelLoadUrl() { 

} 

@Override 
public ExecutorService getThreadPool() { 
    return threadPool; 
} 

@Override 
public Activity getActivity() { 
    return this; 
} 

@Override 
public Context getContext() { 
    return this; 
} 

@Override 
public Object onMessage(final String id, final Object data) { 
    // return getCordovaFragment().onMessage(id, data); 
    return null; 
} 

@Override 
public void setActivityResultCallback(CordovaPlugin arg0) { 
    // TODO Auto-generated method stub 

} 

@Override 
public void startActivityForResult(CordovaPlugin plugin, Intent intent, int requestCode) { 
    mActivityResultCallback = plugin; 
    startActivityForResult(intent, requestCode); 
} 

@Override 
/** 
* Called when the system is about to start resuming a previous activity. 
*/ 
protected void onPause() { 
    super.onPause(); 

    // Send pause event to JavaScript 
    this.cordovaWebView.loadUrl("javascript:try{cordova.fireDocumentEvent('pause');}catch(e){console.log('exception firing pause event from native');};"); 

    // Forward to plugins 
    if (this.cordovaWebView.pluginManager != null) { 
     this.cordovaWebView.pluginManager.onPause(true); 
    } 
    threadPool.shutdown(); 
    threadPool = null; 
} 

@Override 
/** 
* Called when the activity will start interacting with the user. 
*/ 
protected void onResume() { 
    super.onResume(); 

    threadPool = Executors.newCachedThreadPool(); 

    if (this.cordovaWebView == null) { 
     return; 
    } 

    // Send resume event to JavaScript 
    this.cordovaWebView 
      .loadUrl("javascript:try{cordova.fireDocumentEvent('resume');}catch(e){console.log('exception firing resume event from native');};"); 

    // Forward to plugins 
    if (this.cordovaWebView.pluginManager != null) { 
     this.cordovaWebView.pluginManager.onResume(true); 
    }  
} 

@Override 
/** 
* The final call you receive before your activity is destroyed. 
*/ 
public void onDestroy() { 
    super.onDestroy(); 
    if (cordovaWebView.pluginManager != null) { 
     cordovaWebView.pluginManager.onDestroy(); 
    } 

    if (this.cordovaWebView != null) { 

     // Send destroy event to JavaScript 
     this.cordovaWebView 
       .loadUrl("javascript:try{cordova.require('cordova/channel').onDestroy.fire();}catch(e){console.log('exception firing destroy event from native');};"); 

     // Load blank page so that JavaScript onunload is called 
     this.cordovaWebView.loadUrl("about:blank"); 

     // Forward to plugins 
     if (this.cordovaWebView.pluginManager != null) { 
      this.cordovaWebView.pluginManager.onDestroy(); 
     } 
    } else { 
     // this.endActivity(); 
    } 
} 
} 

编辑:这里是logcat的输出;

11-23 12:25:36.117: E/AndroidRuntime(9645): FATAL EXCEPTION: main 

11-23 12:25:36.117: E/AndroidRuntime(9645): java.lang.RuntimeException: Unable to  destroy activity  {org.apache.cordova.example/okan.apps.nativeview.MainNativeViewController}:  java.lang.IllegalArgumentException: Receiver not registered:  [email protected] 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3655) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3673) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ActivityThread.access$2900(ActivityThread.java:125) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.os.Handler.dispatchMessage(Handler.java:99) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.os.Looper.loop(Looper.java:123) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at java.lang.reflect.Method.invokeNative(Native Method) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at java.lang.reflect.Method.invoke(Method.java:521) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at dalvik.system.NativeStart.main(Native Method) 
11-23 12:25:36.117: E/AndroidRuntime(9645): Caused by: java.lang.IllegalArgumentException: Receiver not registered: [email protected] 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ActivityThread$PackageInfo.forgetReceiverDispatcher(ActivityThread.java:793) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:814) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:331) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at org.apache.cordova.Device.onDestroy(Device.java:98) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at org.apache.cordova.api.PluginManager.onDestroy(PluginManager.java:317) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at okan.apps.nativeview.MainNativeViewController.onDestroy(MainNativeViewController.java:204) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3642) 
11-23 12:25:36.117: E/AndroidRuntime(9645):  ... 11 more 

编辑:

我结束了一个解决方案。我在片段中使用Cordova Web View,我将它从片段中移出,并将其放入与片段容器相同的xml中。现在它没有错误地工作。它在GitHub中的示例项目中相同,CordovaWebView在FrameLayout中。

回答

1

你并不需要实现全毁流自己,你可以使用以下命令:

public void onDestroy() { 
    LOG.d("Destroying the View", "onDestroy()"); 
    super.onDestroy(); 

    if (this.cwv != null) { 
    this.cwv.handleDestroy(); 
    } 
} 

希望这有助于。

+0

嘿,我想你的解决方案,但我仍然得到同样的错误。它说, '活动MainNativeViewController泄漏了最初在这里注册的IntentReceiver [email protected]。你是否错过了一个对unregisterReceiver()的调用?' – osayilgan

+0

嘿,我猜我找到了方法,我在handleDestroy()之前调用了'this.cwv.removeAllViews();' ,它似乎有效。我不再犯错误,但我不知道它的正确方法? – osayilgan

+0

**编辑:**以这种方式它被破坏没有错误,但在我试图再次启动应用程序后,摧毁它,然后我得到另一个错误,说,''java.lang.IllegalStateException:无法执行此操作onSaveInstanceState之后的动作“' – osayilgan

4

我在片段解决了这个通过添加以下到onDestroyView()

@Override 
    public void onDestroyView() { 
     super.onDestroyView(); 
     mCordovaWebView.handleDestroy(); 

    } 
+0

不确定你使用的是哪个版本的Cordova,但是(可能在更新版本中已经解决了),那个时候,当我问这个问题时,你的解决方案不起作用。 – osayilgan

+0

我在Android上使用3.6.4。然而,我上面的解决方案似乎已经在退出时引入了'''java.lang.IllegalArgumentException:Receiver not registered:org.apache.cordova.App''' ... 我最终在这里,因为使用后退按钮完成应用程序给我'''活动MainNativeViewController已泄漏IntentReceiver [email protected]最初注册在这里。你是否错过了一个调用unregisterReceiver()''' 这似乎与你最初看到的相反。 – theSociableme

+0

如果你看到这个异常,那么在添加上面的@Yoel解决方案之后它是同样的问题。所以,而不是使用onDestroy,如果你在onDestroyView中调用handleDestroy解决了这个问题? – osayilgan