屏幕接收器在我的服务中不起作用

时间:2012-05-09 20:29:24

标签: android android-service

我正试图让我的屏幕开启/关闭以使用我的服务,但到目前为止还没有运气。

目标是:当屏幕变为OFF时,让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;
}

我遵循了一个关于如何让我的服务与Receiver进行交互的教程,以及最后没有类似内容的源代码,任何猜测?

祝你好运

<?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();
}

}

1 个答案:

答案 0 :(得分: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方法中启动AGAIN服务。这不是android服务的工作方式。 正确的方法是从服务的onCreate方法实例化和注册接收器,并从应用程序的另一个点启动服务,例如,如果它是app-widget,您可以从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));

  4. 这里发生的是:

    当startService执行时,实例化您的服务并执行onCreate方法,其中接收者已注册并开始监视Intents。然后调用服务的onStart方法并返回START_STICKY,这意味着如果从系统终止服务将重新启动,因此接收器将再次注册,依此类推。 BTW只要你的服务终止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;
        }
    }
    

    您正在声明一个intent并且您正在使用它来启动服务,但您没有指定要启动的服务。我认为你缺少像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);
    }
    

    希望这会有所帮助......