Android - Toast 调用上的空指针

Android - Null pointer on Toast call

我有一个 服务,它通过 JNI 调用 C 函数。然后这个函数生成一个 pthread 并将它附加到 JVM。我从这个 pthread 调用一个 Java 方法,它应该 post 一个 Toast 通知。不幸的是,一旦调用 Toast 通知,我就会收到 空指针异常

这是在我的服务中处理 Toast 调用的方法 class:

public void showToast(final String msg) {
    final Context MyContext = this;
    Handler h = new Handler(MyContext.getMainLooper());
    h.post(new Runnable() {
        @Override
        public void run() {
            Toast myToast = Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT);
            myToast.show();
        }
    });
}

什么可能导致空指针异常,我该如何解决

是否尝试从 C 函数获取上下文失败?

这是错误信息

W/dalvikvm( 4010): JNI WARNING: JNI method called with exception pending
W/dalvikvm( 4010):              in Ldalvik/system/NativeStart;.run:()V (CallVoidMethod)
W/dalvikvm( 4010): Pending exception is:
I/dalvikvm( 4010): java.lang.NullPointerException:
I/dalvikvm( 4010):  at android.content.ContextWrapper.getMainLooper(ContextWrapper.java:104)

使用getApplicationContext:

I/dalvikvm( 6242): java.lang.NullPointerException:
I/dalvikvm( 6242):  at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:109)

试试这个:

Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT).show();

我一直都是这样做的,只有当 msg 不为空时它才会崩溃。

尝试一下,如果不起作用,请检查 msg 之前是否为空。你可以这样做。

if (msg.equals(null){
msg = "Variable was null";
}
Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT).show();

顺便说一句,我忘了考虑你可能不明白这意味着什么。

如果您在 运行 您的应用程序时收到 toast 消息 Variable was null。这意味着无论方法调用来自何处,都会发送一个空字符串。您需要找到方法调用并弄清楚为什么它传递的变量为空。

例如,在您的项目中搜索此 showToast(

搜索那个电话,搜索多少次就搜索多少次。如果有多个调用,您可以在每次调用之前检查字符串,如果它为空,您可以添加一个字符串来帮助您识别调用的来源。您可以使用我在每次调用之前放在上面的代码,而是检查发送的变量。然后使它等于 "call from xxxxx is null""" xxxx 是调用的位置。那么你可以弄清楚为什么发送的变量为空。

也试试我说的用 getApplicationContext() 而不是 MyContext

问题是,当通过 JNI 从 C 线程调用时,我们无法获取上下文。我们必须从服务线程本身获取上下文。为此:

public class MyService extends Service{
    private static Context MyContext; /* get context to use when displaying toast from JNI*/

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public void onDestroy() {
    }

    @Override
    public int onStartCommand(Intent intent,int flags, int startid){
        MyContext = getApplicationContext();
        // do what you need to
        return START_STICKY;
    }

    public void showToast(final String msg) {
        Handler h = new Handler(MyContext.getMainLooper());
        h.post(new Runnable() {
            @Override
            public void run() {
            Toast myToast = Toast.makeText(MyContext, msg, Toast.LENGTH_SHORT);
            myToast.show();
            }
        });
    }
}

这样,我们就有了对正确上下文的静态引用,我们可以通过 JNI 的调用访问该上下文