0

我正在尝试打开/关闭屏幕以在我的服务上工作,但到目前为止还没有运气。

目标是:当屏幕关闭时让 LED 灯(软键)熄灭,当屏幕重新打开时,使用用户在我的应用程序上输入的值打开软键灯(您将看到 TextXLActivity.getledC()从主要活动中获取 Int )

在我的主要活动中,我可以毫无问题地控制 LED 灯,使用 SeekBar 等。唯一不起作用的是接收器/服务

现在,当我转到设置、应用程序、运行服务时,我的应用程序没有在任何地方列出,我担心我的服务根本没有启动,也许这就是问题所在。

这是我的接收器:

package com.test.xl;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class ScreenReceiver extends BroadcastReceiver {

private boolean screenOff;

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
        screenOff = true;
    } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
        screenOff = false;
    }
    Intent i = new Intent(context, UpdateService.class);
    i.putExtra("screen_state", screenOff);
    context.startService(i);
}



}

这里是我的服务:

package com.test.xl;




import com.sonyericsson.illumination.IlluminationIntent;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;

public class UpdateService extends Service {

@Override
public void onCreate() {
    super.onCreate();
    // register receiver that handles screen on and screen off logic
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ScreenReceiver();
    registerReceiver(mReceiver, filter);

}
@Override
public void onStart(Intent intent, int startId) {
    boolean screenOn = intent.getBooleanExtra("screen_state", false);
    if (!screenOn) {

        {
            Intent led = new Intent(IlluminationIntent.ACTION_START_LED);
            led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
            led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
            led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, TestXLActivity.getledC());
            startService(led);
        }

    } else {


        Intent led = new Intent(IlluminationIntent.ACTION_STOP_LED);
        led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, 0xFFFFFFFF);
        startService(led);

    }
}

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

}

这是一个测试应用程序,我开始尝试了解接收器/服务“关系”,任何帮助将不胜感激!;)

我还注意到我的服务迫使我实施以下几行:

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

我遵循了一个关于如何让我的服务与接收器交互的教程,并且源代码最后没有类似的东西,有什么猜测吗?

此致

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.xl"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk android:minSdkVersion="10"/>
<uses-permission android:name="com.sonyericsson.illumination.permission.ILLUMINATION"/>

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:name=".TestXLActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
            <receiver android:name=".ScreenReceiver">
 <intent-filter>
<action android:name="android.intent.action..ACTION_SCREEN_ON" />
<action android:name="android.intent.action.ACTION_SCREEN_OFF" />
</intent-filter>
</receiver>

        </intent-filter>
    </activity>
</application>

</manifest>

编辑:这是出现错误的源代码(startService(led)):

package com.test.xl;

import com.sonyericsson.illumination.IlluminationIntent;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class ScreenReceiver extends BroadcastReceiver {

private boolean screenOff;

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {

        Intent led = new Intent(IlluminationIntent.ACTION_STOP_LED);
        led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, 0xFFFFFFFF);
        startService(led);
        screenOff = true;
    } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {

        Intent led = new Intent(IlluminationIntent.ACTION_START_LED);
        led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, TestXLActivity.getledC());
        startService(led);
        screenOff = false;
    }

}

}

新代码

public class ScreenReceiver extends BroadcastReceiver {

private boolean screenOff;

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {

        Intent led = new Intent(IlluminationIntent.ACTION_STOP_LED);
        led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, 0xFFFFFFFF);
        context.startService(led);
        screenOff = true;
    } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {

        int ledC = TestXLActivity.getledC();

        Intent led = new Intent(IlluminationIntent.ACTION_START_LED);
        led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, ledC);
        context.startService(led);
        screenOff = false;
    }

}

.

public class UpdateService extends Service {

private ScreenReceiver mReceiver = null;

@Override
public void onCreate() {
    super.onCreate();
    // register receiver that handles screen on and screen off logic
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    if(mReceiver != null)mReceiver = new ScreenReceiver();
    registerReceiver(mReceiver, filter);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    return Service.START_STICKY;
}

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

@Override
public void onDestroy() {
    unregisterReceiver(mReceiver);
    super.onDestroy();
}

}

4

1 回答 1

4

我认为您的问题是您的 BroadcastReceiver mReceiver 在您的服务的 onCreate 方法之后无法生存。此外,您没有声明它是正确的。如果我是你,我会做这样的事情:

public class UpdateService extends Service {

private ScreenReceiver mReceiver = null;

@Override
public void onCreate() {
    super.onCreate();
    // register receiver that handles screen on and screen off logic
    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    if(mReceiver != null)mReceiver = new ScreenReceiver();
    registerReceiver(mReceiver, filter);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    *** NOTE HERE THAT I AM OVERRIDING THE ONSTART AS AN INT NOT VOID***

    .... do your stuff here....

    return Service.START_STICKY;
}

现在你的方法还有另一个问题。您在服务的 onCreate 方法中声明和实例化您的接收器,然后您从接收器的 onReceive 方法中再次启动服务。这不是 android 服务的工作方式。正确的方法是从服务的 onCreate 方法实例化和注册您的接收器,并从应用程序的另一个点启动服务,例如,如果它是一个应用程序小部件,您可以从 WidgetProvider 的 onUpdate 方法或从一些 Activity 的 onCreate 方法。

所以你的代码应该如下:

  1. 您的接收器:

    public class ScreenReceiver extends BroadcastReceiver {
    
        private boolean screenOff;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                screenOff = true;
            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                screenOff = false;
            }
    
            ... Do your stuff here for screen on or off ....
            ... AND DO NOT START A SERVICE FROM HERE ....
        }
    }
    
  2. 您的服务:

    public class UpdateService extends Service {
    
        private ScreenReceiver mReceiver = null;
    
        @Override
        public void onCreate() {
            super.onCreate();
            // register receiver that handles screen on and screen off logic
            IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
            filter.addAction(Intent.ACTION_SCREEN_OFF);
            if(mReceiver != null)mReceiver = new ScreenReceiver();
            registerReceiver(mReceiver, filter);
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            NOTE HERE THAT I AM OVERRIDING THE ONSTART AS AN INT NOT VOID
    
            .... YOU DON'T HAVE TO DO SOMETHING HERE EXCEPT FROM SOME ....
            .... INITIALIZATION CODE ...
    
            return Service.START_STICKY;
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onDestroy() {
            UnregisterReceiver(mReceiver);
            super.onDestroy();
        }
    }
    
  3. 您的活动或其他代码点:

    startService(new Intent(context, UpdateService.class));

这里发生的是这样的:

当 startService 执行时,您的服务会被实例化,并且 onCreate 方法会执行,在该方法中注册接收器并开始监视 Intent。然后调用服务的 onStart 方法并返回 START_STICKY ,这意味着如果从系统中终止服务将重新启动,因此接收者将再次注册,依此类推。顺便说一句,每当您的服务终止 onDestroy 方法将被调用并且接收器将被取消注册(这是一件非常糟糕的事情)。

现在,您已经准备好随时运行服务以接收来自系统的通知。

如果您希望在某个时候终止服务,只需调用

context.stopService(new Intent(context, UpdateService.class));

我并不真正深入了解 Android 服务,但这种技术非常适用于我的服务,该服务同时托管一个 BroadcastReceiver 和一个 ContentObserver。

根据您的新进展进行编辑

好的,现在看来我们正在取得进展。我可以在您的 onReceive 方法中看到

@Override
public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
        Intent led = new Intent(IlluminationIntent.ACTION_STOP_LED);
        led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, 0xFFFFFFFF);
        context.startService(led);
        screenOff = true;
    } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {

        int ledC = TestXLActivity.getledC();

        Intent led = new Intent(IlluminationIntent.ACTION_START_LED);
        led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, ledC);
        context.startService(led);
        screenOff = false;
    }
}

您正在声明一个引导的意图,并且您正在使用它来启动服务,但您没有指定要启动哪个服务。我认为你缺少像 led.setClass 这样的东西。但是为了稍微清楚一点,让我们像这样修改 onReceive:

@Override
public void onReceive(Context context, Intent intent) {
    Intent led = new Intent(context, your_led_service_name.class);
    led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");

    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
        led.addAction(IlluminationIntent.ACTION_STOP_LED);
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, 0xFFFFFFFF);
        context.startService(led);
        screenOff = true;
    } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
        int ledC = TestXLActivity.getledC();
        led.addAction(IlluminationIntent.ACTION_START_LED);
        led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, ledC);
        context.startService(led);
        screenOff = false;
    }
}

看看现在情况如何……

第二次编辑

好的,我对 Sony Ericsson Illumination API 一无所知,但根据您的代码,您可能需要按如下方式更改 onReceive:

@Override
public void onReceive(Context context, Intent intent) {
    IlluminationIntent led = new IlluminationIntent(??);
    //Note: In place of ?? you may need your context on nothing at all
    //it depends on sony's API.

    led.putExtra(IlluminationIntent.EXTRA_PACKAGE_NAME, "com.test.xl");

    led.putExtra(IlluminationIntent.EXTRA_LED_ID, IlluminationIntent.VALUE_BUTTON_2);
    //This is only needed once...

    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
        led.addAction(IlluminationIntent.ACTION_STOP_LED);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, 0xFFFFFFFF);
        screenOff = true;
    } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
        int ledC = TestXLActivity.getledC();
        led.addAction(IlluminationIntent.ACTION_START_LED);
        led.putExtra(IlluminationIntent.EXTRA_LED_COLOR, ledC);
        screenOff = false;
    }

    context.startService(led);
}

希望这可以帮助...

于 2012-05-09T22:00:48.433 回答