2010-06-06 53 views
26

我想运行一个Android后台服务,它将充当主屏幕上的键盘记录程序或手机处于睡眠状态。这可能吗?是否有可能创建一个监听硬件按键的Android服务?

从半在线的相关示例中,我将以下服务放在一起,但得到错误,“onKeyDown未定义类型服务”。这是否意味着如果不重写Launcher就不能完成这项工作,或者有什么明显的我失踪了?

public class ServiceName extends Service { 

    @Override 
    public void onCreate() { 
     //Stuff 
    } 

    public IBinder onBind(Intent intent) { 
     //Stuff 
     return null; 
    } 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     if(event.getAction() == KeyEvent.ACTION_DOWN) { 
     switch(keyCode) { 
     case KeyEvent.KEYCODE_A: 
      //Stuff 
      return true; 
     case KeyEvent.KEYCODE_B: 
      //Stuff 
      return true; 

      //etc. 
     } 
     } 

     return super.onKeyDown(keyCode, event); 
    } 
} 

我意识到Android的默认搜索栏,当你从主屏幕上打字,但是这真的仅仅是一个非常特殊的用途。除了我之外,我没有真正希望有人想要这样。我只是觉得它会很好,例如,使用相机按钮来唤醒手机。

+2

HIII 如果你已经找到解决类似的问题,然后让我know.thnx – 2012-02-13 08:07:01

回答

16

据我所知,KeyEvents只能由活动处理,因为它们是用户按键的界面。服务在后台运行,并不打算对用户输入做出反应。这也是编译器警告的原因“onKeyDown未定义类型Service”。服务或其任何超类不实现KeyEvent.Callback接口。作为解决方法,您可以在您的AndroidManifest.xml中注册一个活动,以对某些系统通知(例如android.intent.action.SCREEN_ON)作出反应。当按下电源按钮打开屏幕时,您的活动可能会启动,初始化某种服务并返回到背景。如果那是你打算做的。有关可能的操作,请参阅Intent docs

希望这有助于...

+1

很抱歉,如果我误解了。罗曼盖伊在Android团队工作,他[确认](http://stackoverflow.com/a/3455094/942821)。 – 2012-07-09 14:50:00

0

虽然不可能直接在服务监听硬件按键,你有时可以听这些按键的效果。例如,this answer描述了如何根据媒体音量的变化推断音量按键。

0

这需要棒棒糖(V5.0/API 21)或更高,并且只能检测音量键

它将会覆盖音量键作用,因此使用它全局可能不期望。

public class VolumeKeyController { 

    private MediaSessionCompat mMediaSession; 
    private final Context mContext; 

    public VolumeKeyController(Context context) { 
     mContext = context; 
    } 

    private void createMediaSession() { 
     mMediaSession = new MediaSessionCompat(mContext, KeyUtil.log); 

     mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | 
       MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); 
     mMediaSession.setPlaybackState(new Builder() 
       .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0) 
       .build()); 
     mMediaSession.setPlaybackToRemote(getVolumeProvider()); 
     mMediaSession.setActive(true); 
    } 

    private VolumeProviderCompat getVolumeProvider() { 
     final AudioManager audio = mContext.getSystemService(Context.AUDIO_SERVICE); 

     int STREAM_TYPE = AudioManager.STREAM_MUSIC; 
     int currentVolume = audio.getStreamVolume(STREAM_TYPE); 
     int maxVolume = audio.getStreamMaxVolume(STREAM_TYPE); 
     final int VOLUME_UP = 1; 
     final int VOLUME_DOWN = -1; 

     return new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) { 
      @Override 
      public void onAdjustVolume(int direction) { 
       // Up = 1, Down = -1, Release = 0 
       // Replace with your action, if you don't want to adjust system volume 
       if (direction == VOLUME_UP) { 
        audio.adjustStreamVolume(STREAM_TYPE, 
          AudioManager.ADJUST_RAISE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); 
       } 
       else if (direction == VOLUME_DOWN) { 
        audio.adjustStreamVolume(STREAM_TYPE, 
          AudioManager.ADJUST_LOWER, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); 
       } 
       setCurrentVolume(audio.getStreamVolume(STREAM_TYPE)); 
      } 
     }; 
    } 

    // Call when control needed, add a call to constructor if needed immediately 
    public void setActive(boolean active) { 
     if (mMediaSession != null) { 
      mMediaSession.setActive(active); 
      return; 
     } 
     createMediaSession(); 
    } 

    // Call from Service's onDestroy method 
    public void destroy() { 
     if (mMediaSession != null) { 
      mMediaSession.release(); 
     } 
    } 
} 
相关问题