将android中的服务引入前台

时间:2011-03-28 10:27:54

标签: android android-service

我有一个Android服务,我不希望手机自动禁用服务。 因此,我尝试将通知发送到通知栏。 当我尝试这样做时,我的HTC Hero重新启动。

我使用以下代码,出了什么问题?它部分复制自reference。 是否有一个很好的教程解释了这个API的工作原理?

private static final Class<?>[] mSetForegroundSignature = new Class[] {
    boolean.class};
private static final Class<?>[] mStartForegroundSignature = new Class[] {
    int.class, Notification.class};
private static final Class<?>[] mStopForegroundSignature = new Class[] {
    boolean.class};

private NotificationManager mNM;
private Method mSetForeground;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mSetForegroundArgs = new Object[1];
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];

void invokeMethod(Method method, Object[] args) {
    try {
        mStartForeground.invoke(this, mStartForegroundArgs);
    } catch (InvocationTargetException e) {
        // Should not happen.
        Log.w("ApiDemos", "Unable to invoke method", e);
    } catch (IllegalAccessException e) {
        // Should not happen.
        Log.w("ApiDemos", "Unable to invoke method", e);
    }
}

/**
 * This is a wrapper around the new startForeground method, using the older
 * APIs if it is not available.
 */
void startForegroundCompat(int id, Notification notification) {
    // If we have the new startForeground API, then use it.
    if (mStartForeground != null) {
        mStartForegroundArgs[0] = Integer.valueOf(id);
        mStartForegroundArgs[1] = notification;
        invokeMethod(mStartForeground, mStartForegroundArgs);
        return;
    }

    // Fall back on the old API.
    mSetForegroundArgs[0] = Boolean.TRUE;
    invokeMethod(mSetForeground, mSetForegroundArgs);
    mNM.notify(id, notification);
}

/**
 * This is a wrapper around the new stopForeground method, using the older
 * APIs if it is not available.
 */
void stopForegroundCompat(int id) {
    // If we have the new stopForeground API, then use it.
    if (mStopForeground != null) {
        mStopForegroundArgs[0] = Boolean.TRUE;
        try {
            mStopForeground.invoke(this, mStopForegroundArgs);
        } catch (InvocationTargetException e) {
            // Should not happen.
            Log.w("ApiDemos", "Unable to invoke stopForeground", e);
        } catch (IllegalAccessException e) {
            // Should not happen.
            Log.w("ApiDemos", "Unable to invoke stopForeground", e);
        }
        return;
    }

    // Fall back on the old API.  Note to cancel BEFORE changing the
    // foreground state, since we could be killed at that point.
    mNM.cancel(id);
    mSetForegroundArgs[0] = Boolean.FALSE;
    invokeMethod(mSetForeground, mSetForegroundArgs);
}

private void setupNotification(){
    mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    try {
        mStartForeground = getClass().getMethod("startForeground",
                mStartForegroundSignature);
        mStopForeground = getClass().getMethod("stopForeground",
                mStopForegroundSignature);
    } catch (NoSuchMethodException e) {
        // Running on an older platform.
        mStartForeground = mStopForeground = null;
        return;
    }
    try {
        mSetForeground = getClass().getMethod("setForeground",
                mSetForegroundSignature);
    } catch (NoSuchMethodException e) {
        throw new IllegalStateException(
                "OS doesn't have Service.startForeground OR Service.setForeground!");
    }

    CharSequence text = getText(R.string.notification_active_text);
    // Set the icon, scrolling text and timestamp
    Notification notification = new Notification(R.drawable.icon, text,
            System.currentTimeMillis());
    startForegroundCompat(
            R.string.foreground_service_started, 
            notification);

}

2 个答案:

答案 0 :(得分:3)

好吧,它不应该重新启动,但样本中的代码至少有两个主要错误,并且不会按预期工作。我已经使用Android 1.6模拟器对其进行了测试,只有在以下更改后才能使用它:

  1. invokeMethod()显然是错误的,因为它忽略了传递的参数并改为进行固定的方法调用。 IntelliJ IDEA可以轻松发现此问题,修复程序将mStartForeground.invoke(this, mStartForegroundArgs);更改为method.invoke(this, args);
  2. {li> original sample中的onCreate()不会在1.6上初始化 mSetForeground ,因为 return 语句位于第一个捕获,而它必须在第一个尝试中。尝试启动服务时,您将获得NPE。在mStartForeground = mStopForeground = null;之后删除返回并将其放在mStopForeground = getClass().getMethod("stopForeground", mStopForegroundSignature);之后将解决此问题。

    更新:Google似乎已经修复了the sample,它应该可以正常使用。

答案 1 :(得分:0)

谷歌没有解决这个问题。 对我有用的是把它放在开头而不是他们使用的东西:

private static final Class<?>[] mSetForegroundSignature   = new Class[] {Boolean.TYPE};
private static final Class<?>[] mStartForegroundSignature = new Class[] {Integer.TYPE, Notification.class};
private static final Class<?>[] mStopForegroundSignature  = new Class[] {Boolean.TYPE};