如何从Android Service中获取应用程序上下文?

17

我有一个正在运行并监听麦克风输入的安卓服务。当满足特定条件时,我希望它可以启动一个活动。为了创建一个Intent,我需要应用程序上下文。如何获取它?

Intent i = new Intent(ctx, SONR.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ctx.startActivity(i);

上述代码行并未启动我的活动。

这是我的构造函数

public SONRClient(Context c, AudioRecord ar, int buffsize, final AudioManager am) {
    theAudioManager = am;
    theaudiorecord = ar;
    bufferSize = buffsize;
    ctx = c;
    CLIENT_ON = true;
}

这是我的onCreate方法

@Override
public void onCreate() {
    try {
        // LogFile.MakeLog("\n\nSONRClient CREATED");
        clientStopReceiver = new StopReceiver();
        ctx.registerReceiver(clientStopReceiver, 
            new IntentFilter(SONR.DISCONNECT_ACTION));
        myByteReceiver = new SONRByteReceiver();
        theListener = new MicSerialListener(
            theaudiorecord, bufferSize, myByteReceiver);
        theApplication = getApplication();
    } catch (Exception e) {
        e.printStackTrace();
        ErrorReporter.getInstance().handleException(e);
    }
}

我有一个名为myByteReceiver的接收器,通过音频输入监听信号。当它发现匹配的信号时,我想启动一个活动。

private class SONRByteReceiver implements ByteReceiver {
    private long lastplaytime = 0;
    private long lastmutetime = 0;
    private long lastskiptime = 0;
    private long lastvolutime = 0;
    private long lastbacktime = 0;

    public void receiveByte(int receivedByte) {
        try {
            theKeyEvent = -1;

            if (ismuted) {
                if (receivedByte != MUTE) {
                    volume = 0;
                    ismuted = false;
                }
            }

            switch (receivedByte) {

            case SONR_HOME:
                Log.d(TAG, "HOME");

                Intent i = new Intent(ctx, SONR.class);
                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                theApplication.startActivity(i);

                break;
            default:
                Log.d(TAG, "default");
                Log.d(TAG,"RECEIVED " + receivedByte);
                // LogFile.MakeLog("RECEIVED " + receivedByte);
                break;
            }

            if (theKeyEvent >= 0) {
                sendbroadcast();
            }
        } catch (Exception e) {
            e.printStackTrace();
            ErrorReporter.getInstance().handleException(e);
        }
    }
}

以下是堆栈跟踪信息

java.lang.NullPointerException
    at com.sonrlabs.test.sonr.SONRClient$SONRByteReceiver.receiveByte(SONRClient.java:320)
    at com.sonrlabs.test.sonr.AudioProcessor.processSample(AudioProcessor.java:145)
    at com.sonrlabs.test.sonr.AudioProcessor.run(AudioProcessor.java:58)

第320行是 theApplication.startActivity(i);


1
你能发布一下你在哪个方法中调用了 getApplicationContext 吗? - skynet
如果您能发布NullPointerException的日志信息,将更有助于解决问题。 - keno
你的代码中似乎没有任何东西被分配到 ctx 变量中。请检查你的代码,找出 "ctx" 被赋值的地方,并在其周围添加一些打印语句,以便查看是否成功分配了值。 - keno
ctx被分配在我的构造函数中。我也可以发布那段代码。 - Sheehan Alam
我还从我的上下文中打印出包名。这样做很好。问题在于startActivity。不确定原因。 - Sheehan Alam
显示剩余2条评论
9个回答

6

4
当我尝试使用getApplicationContext()时,会出现空指针异常。 - Sheehan Alam
我更新了我的代码。我有上下文的引用,但我的活动没有显示出来。我做错了什么吗? - Sheehan Alam
你是如何启动服务的?你能否编辑你的问题,提供更完整的服务代码,例如你尝试在哪些生命周期方法中启动活动? - skynet
1
尝试将 theApplication = getApplication(); 移动到 onCreate 的第一行。 - skynet
仍然在theApplication.startActivity(i);处遇到了空指针异常。 - Sheehan Alam

5
每个服务都有自己的上下文,只需使用它即可。您不需要向服务传递活动的上下文。
服务中不需要活动上下文。
Intent i = new Intent(ctx, SONR.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);

只需像在Activity中一样执行即可

Service和Activity都是Context的子类。


2

将此更改为:

Intent i = new Intent(ctx, SONR.class); 

to:

Intent i = new Intent(getApplicationContext(),SONR.class);

不可能,你在其他地方得到了空指针异常。如果你的服务正在运行,那么上下文就不可能为空。 - Rohit
试着点击这一行代码: at com.sonrlabs.test.sonr.AudioProcessor.processSample(AudioProcessor.java:145) 或它上下的代码行,找到哪里出现了null。 - Rohit

1
你所断言的需要应用程序上下文才能启动活动是不准确的。你可以从任何上下文,包括服务(即上下文),启动一个活动

我尝试使用startActivity(),但仍然出现了nullpointerexception。已更新问题并添加更多代码。 - Sheehan Alam
显示空指针的堆栈跟踪。如果您在该类内部使用它,则不是由于空服务。 - dhaag23
问题中的堆栈跟踪是我在调试时打印的所有内容。有什么更深入的调试想法吗? - Sheehan Alam

1

getBaseContext() 返回上下文,因为每个活动都扩展了Context类


1

在其公共空构造函数内调用getApplicationContext()是不允许的,否则将会导致NullPointerException


Service类中,哪里是调用getApplicationContext()的安全位置? - JJD
@JJD 不要调用 getApplicationContext(),调用 getBaseContext(),就像 Vishal Android 开发者所写的那样。 - joninx
问题仍然存在,以哪种方法调用它是安全的。 - JJD

0
只有在Service的'onCreate()'之后才会有一个非空的上下文:在构造函数中获取服务的上下文不是一个好主意(此时还没有任何上下文),应该在'onCreate'方法中使用简单的'getApplicationContext()'来获取它。

-1

只需这样做即可访问服务上下文

Intent i = new Intent(Service.this, SONR.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);

-2
ctx.getApplicationContext().startActivity(i)

砰!


什么是 ctx??您是否从服务中启动上面的指令? - Lisitso
@Lisitso ctx 是一个 Context 变量。 - user2742371
5
如果您已经有了Context类型的ctx变量,为什么还要获取应用程序上下文并使用startActivity?为什么不直接使用ctx.startActivity()? - Ishaan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接