Bri*_*ian 28 android keyevent listener
我想运行一个Android后台服务,它将从主屏幕或手机处于睡眠状态时充当keylistener.这可能吗?
从在线的半相关示例中,我将以下服务放在一起,但得到错误,"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);
}
}
Run Code Online (Sandbox Code Playgroud)
当你从主屏幕输入时,我意识到Android默认为搜索栏,但这只是一个非常特殊的用途.除了我,我真的不希望有人想要这个.我认为,例如,使用相机按钮唤醒手机会很不错.
Mar*_*oB. 16
据我所知,KeyEvents只能由Activities处理,因为它们是用户按键的界面.服务在后台运行,不打算对用户输入做出反应.这也是您的编译器警告"onKeyDown未定义为服务类型"的原因.服务或其任何超类都不实现KeyEvent.Callback接口.作为一种解决方法,您可以在您的注册活动中AndroidManifest.xml
对某些系统通知做出反应,例如android.intent.action.SCREEN_ON
.当按下电源按钮打开屏幕时,您的活动可以启动,初始化某种服务并返回到后台.如果这是你打算做的.有关可能的操作,请参阅Intent文档.
希望有帮助......
它将覆盖音量键操作,因此可能不需要全局使用它。
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
KeyEvents 需要触发 Activity。因此,无法通过服务检测到硬件按键,因为服务没有主机活动。您可以要求 SystemOverlay,并创建一个透明的 Activity。但是这种方法似乎不适用于 API 26+ 设备。
解决方法是通过 AccessibilityServices 设置观察者。这允许您全局检测硬件按键按下。
注意:将应用程序启用为辅助功能应用程序可能会导致重大安全问题,用户会谨慎启用此功能。因此,在您的应用程序对于您的应用程序将处理的数据对用户“透明”的情况下,这将是可取的。此方法适用于所有 API 21+ 设备,我尚未在低于此的设备上进行过测试,因此它可能有效也可能无效。
脚步:
使用以下选项创建一个 XML 文件
<accessibility-service
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
android:settingsActivity=""
android:packageNames="yourpackagename"
android:canRequestFilterKeyEvents="true"
/>
Run Code Online (Sandbox Code Playgroud)在清单中定义您的 AccessibilityService
<service android:name=".Services.AccessibilityKeyDetector"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="@xml/accessibility_layout" />
</service>
Run Code Online (Sandbox Code Playgroud)创建一个 AccessibilityService 类
public class AccessibilityKeyDetector extends AccessibilityService {
private final String TAG = "AccessKeyDetector";
@Override
public boolean onKeyEvent(KeyEvent event) {
Log.d(TAG,"Key pressed via accessibility is: "+event.getKeyCode());
//This allows the key pressed to function normally after it has been used by your app.
return super.onKeyEvent(event);
}
@Override
protected void onServiceConnected() {
Log.i(TAG,"Service connected");
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
}
Run Code Online (Sandbox Code Playgroud)
public class MainActivity extends AppCompatActivity {
private final String TAG = "Test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkAccessibilityPermission();
}
public boolean checkAccessibilityPermission() {
int accessEnabled=0;
try {
accessEnabled = Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (accessEnabled==0) {
/** if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
/** request permission via start activity for result */
startActivity(intent);
return false;
} else {
return true;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(TAG,"Key pressed");
//this prevents the key from performing the base function. Replace with super.onKeyDown to let it perform it's original function, after being consumed by your app.
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
36197 次 |
最近记录: |