Phonegap 和 C2DM - NullPointerException

发布于 2025-01-03 19:36:53 字数 2162 浏览 1 评论 0原文

我将 C2DM 与 PhoneGap 一起使用。当我收到 C2DM 消息时,我会显示一条通知(通过 NotificationManager)。当用户选择通知时,我的应用程序会收到一个意图。在这种情况下,我想激活我的 jquery-mobile web 应用程序中的页面。

因此,我覆盖了 onNewIntent 事件来存储意图:

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

然后,在 onResume 中,如果意图来自 C2DM,我激活了正确的页面:

@Override
protected void onResume()
{
    super.onResume();

    // read possible argument
    boolean showMessage = getIntent().getBooleanExtra(ARG_SHOW_MESSAGES, false);
    if (showMessage)
    {
        clearNotification();
        super.loadUrl("file:///android_asset/www/de/index.html#messages");
    }
}

这工作正常,但有时会崩溃NullPointerException - 不在我的手机或模拟器上,而是在其他设备上。堆栈跟踪显示它位于 DroidGap 活动的 onNewIntent 中,请参阅代码

protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

    //Forward to plugins
    this.pluginManager.onNewIntent(intent);
}

我是'无法重现这种情况。显然,pluginManager 为空,但我不知道为什么。

所以问题是:

  • 从 Android 中选择 jquery-mobile 中的特定页面所采取的方法是否良好,或者有人可以指出更好的方法吗?
  • 我怎样才能摆脱异常?当然,我可以检查pluginManager是否为空,在这种情况下不调用super - 但随后我的特定页面未激活。
  • 您是否认为这是一个 PhoneGap 错误 - 不检查插件管理器是否为空?当我检查 PhoneGap 代码时,我认为这种情况永远不应该发生,根据我的理解, onNewIntent 仅在加载 Activity 时调用,否则将触发 onCreate 。

更新 我现在知道更多了:当应用程序未加载且 C2DM 消息到达时,就会出现问题。 Intent 启动应用程序,事件按以下顺序发生 - 但 onNewIntent 仅偶尔被调用:

onCreate()
onNewIntent()
onResume()

每当 onNewIntent 在启动期间执行时,它就会崩溃。无论如何,我修复了这个问题:

@Override
protected void onNewIntent(final Intent intent)
{
    // avoid Phonegap bug
    if (pluginManager != null)
    {
        super.onNewIntent(intent);
    }
    setIntent(intent);
}

当我想更改 onResume-Event 中的起始页面时,当 Phonegap 未准备好时,这不起作用。因此,在应用程序正在启动的情况下,在 onResume 中调用 #messages 页面还为时过早。但什么时候调用它呢?是否有可能挂钩 onDeviceReady?

I am using C2DM together with PhoneGap. When I receive a C2DM message, I display a notification (via NotificationManager). When the user selects the notification then my application receives an intent. In that case I want to activate a page within my jquery-mobile webapp.

Therefore I overrode the onNewIntent event to store the intent:

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

Then, in onResume I activated the correct page if the intent was from C2DM:

@Override
protected void onResume()
{
    super.onResume();

    // read possible argument
    boolean showMessage = getIntent().getBooleanExtra(ARG_SHOW_MESSAGES, false);
    if (showMessage)
    {
        clearNotification();
        super.loadUrl("file:///android_asset/www/de/index.html#messages");
    }
}

This works fine but it crashes sometimes with a NullPointerException - not on my mobile or emulator, but on other devices. The stacktrace says it is in the onNewIntent of the DroidGap activity, see Code:

protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

    //Forward to plugins
    this.pluginManager.onNewIntent(intent);
}

I wasn't able to reproduce this situation. Obviously pluginManager is null but I don't why.

So the questions are:

  • Is the taken approach to select a specific page in jquery-mobile from Android good or can someone point out a better approach?
  • How can I get rid of the exception? Of course I could check pluginManager for beeing null and in this case don't call super - but then my specific page isn't activated.
  • Do you think this is a PhoneGap bug - not to check pluginmanager for null? When I checked the PhoneGap code I thought this should never happen, in my understanding onNewIntent is only called when the activity is loaded, otherwise onCreate would be triggered instead.

Update
I know more now: problem occurs when the app is not loaded and a C2DM message arrives.
The intent starts the app, the events occur in the following order - but onNewIntent is only called occasionally:

onCreate()
onNewIntent()
onResume()

Whenever onNewIntent is executed during the startup it crashes. Anyway I fixed this with:

@Override
protected void onNewIntent(final Intent intent)
{
    // avoid Phonegap bug
    if (pluginManager != null)
    {
        super.onNewIntent(intent);
    }
    setIntent(intent);
}

When I want to change the start page in the onResume-Event, this doesn't work when Phonegap is not ready. So it is just to early to call the #messages page in onResume in the case that the application is starting. But when to call it then? Is there a possiblility to hook into onDeviceReady?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

隔纱相望 2025-01-10 19:36:53

我仍然不知道为什么有时 onNewIntent 在应用程序启动期间被触发(而不仅仅是激活),有时则不然。无论如何,我通过一些解决方法解决了所有问题。

在我的活动中,我创建了一个新函数(不删除相关部分):

public void onDeviceReady()
{
    if (!isReady)
    {
        super.loadUrl("file:///android_asset/www/en/index.html#messages");
    }

    // activate onResume instead
    isReady = true;
}

以及上面的布尔标志:

/** Is PhoneGap ready? */
private boolean isReady = false;

我在 onCreate 事件中激活回调:

// Callback setzen
appView.addJavascriptInterface(this, "Android");

并从 Javascript onDeviceReady 调用它

if (OSName == "Android")
{
    window.Android.onDeviceReady();
}

在 onResume 事件中,我使用协商逻辑:

protected void onResume()
{
    super.onResume();

    if (isReady)
    {
        super.loadUrl("file:///android_asset/www/en/index.html#messages");
    }
}

这保证页面选择仅在 onResume 或 onDeviceReady 中执行一次。

I still do not know why sometimes onNewIntent is triggered during a application start (not just activated) and sometimes not. Anyway I solved all my problems with some workarounds.

In my activity I created a new function (not relevant parts are stripped):

public void onDeviceReady()
{
    if (!isReady)
    {
        super.loadUrl("file:///android_asset/www/en/index.html#messages");
    }

    // activate onResume instead
    isReady = true;
}

and the boolean flag above:

/** Is PhoneGap ready? */
private boolean isReady = false;

I activate the callback in the onCreate event:

// Callback setzen
appView.addJavascriptInterface(this, "Android");

and call it from the Javascript onDeviceReady

if (OSName == "Android")
{
    window.Android.onDeviceReady();
}

In the onResume event I use the negotiated logic:

protected void onResume()
{
    super.onResume();

    if (isReady)
    {
        super.loadUrl("file:///android_asset/www/en/index.html#messages");
    }
}

This guarantees that the page selection is executed only once, either in onResume or in onDeviceReady.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文