目的:监听手机的物理按键实现相应的功能(给自己的笔记)
Android KeyCode 可以自行网上查找
可根据相应 KeyEvent 进行手机按键事件拦截
可根据相应 KeyCode 执行你想要执行的内容
-------- 实现进入指定页面后,使用音量键时执行自定义任务,而不是调节系统音量
在 MainActivity.java 文件里添加如下方法(一样的不需要重复添加)
package com.demo; // 自己的包名
import com.facebook.react.ReactActivity;
import org.devio.rn.splashscreen.SplashScreen;
import android.os.Bundle;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.res.Configuration;
import android.view.WindowManager;
import android.view.KeyEvent;
import android.support.annotation.Nullable;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactMethod;
public class MainActivity extends ReactActivity {
private NetworkChangeReceiver networkChangeReceiver;
/*
* isLister 音量键控制开关
* true --- 音量键不可调节系统音量
* flase --- 音量键可以调节系统音量
*/
Boolean isLister = false;
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Intent intent = new Intent("onConfigurationChanged");
intent.putExtra("newConfig", newConfig);
this.sendBroadcast(intent);
}
@Override
protected String getMainComponentName() {
return "demoApp";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this, com.demo.R.style.SplashScreenTheme);
super.onCreate(savedInstanceState);
/*
* 主要是RN端不能直接执行MainActivity里面的方法所以需要另外创建可供RN执行的module
* 利用module里面的方法来改变 isLister 的值实现开关功能
*/
// 注册自定义广播 (音开关广播)
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.demo.volume"); // com.demo.volume 命名随意
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);
}
// 音频开关
private class NetworkChangeReceiver extends BroadcastReceiver {
// 收到广播执行的内容
@Override
public void onReceive(Context context, Intent intent) {
// 获取广播中传入的 isLister 的值, 获取不到时取第二个参数,这里是 false
isLister = intent.getBooleanExtra("isLister", false);
}
}
// 发送事件给RN端 的方法
private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
}
// 监听手机按键
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
ReactContext reactContext = getReactInstanceManager().getCurrentReactContext();
WritableMap params = Arguments.createMap();
params.putInt("keyCode", event.getKeyCode());
if (event.getAction() == KeyEvent.ACTION_DOWN) {
// 发送keydown事件给RN端
sendEvent(reactContext, "keydown", params); // keydown 可自己命名
} else if (event.getAction() == KeyEvent.ACTION_UP) {
// 发送keyup事件给RN端
sendEvent(reactContext, "keyup", params); // keyup 可自己命名
}
return super.dispatchKeyEvent(event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// 覆盖音量键弹起事件 (这样就不会出现调节音量的弹窗)
// 也可以自己根据别的 KeyEvent 事件来拦截相应操作
if (isLister && keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
return true;
} else if (isLister && keyCode == KeyEvent.KEYCODE_VOLUME_UP){
return true;
} else {
return super.onKeyUp(keyCode, event);
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
// 覆盖音量键按下事件 (这样就不会出现调节音量的弹窗)
if (isLister && keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
return true;
} else if (isLister && keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
}
- 在 MainActivity.java 的同级目录下新建 keyeventlister 文件夹
- 在 keyeventlister 文件夹下新建 KeyEventListerModule.java
package com.demo.keyeventlister; // 自己的包名 + keyeventlister
import android.content.Intent;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReactContext;
public class KeyEventListerModule extends ReactContextBaseJavaModule{
private ReactApplicationContext mContext;
KeyEventListerModule(ReactApplicationContext reactContext) {
super(reactContext);
mContext = reactContext;
}
@Override
public String getName() {
return "KeyEventLister";
}
// 开关音量键 (提供给RN端使用的方法)
@ReactMethod
public void audioSwitch(final Boolean isLister) {
getCurrentActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Intent intent = new Intent();
intent.putExtra("isLister", isLister); // 添加广播传送的参数
intent.setAction("com.demo.volume"); // 需跟注册广播时填写的一致
//发送广播
getCurrentActivity().sendBroadcast(intent);
}
});
}
}
在 keyeventlister 文件夹下创建 KeyEventListerPackage.java
package com.demo.keyeventlister;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class KeyEventListerPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new KeyEventListerModule(reactContext));
return modules;
}
}
修改 MainApplication.java
// 在头部引入
import com.demo.keyeventlister.KeyEventListerPackage;
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
// 这里添加如下package ↓↓↓
new KeyEventListerPackage()
);
}
Example.js
import React, { Component } from 'react';
import { View, NativeModules } from 'react-native';
export default class Example extends Component {
constructor(props) {
super(props);
this.state = {
}
keyEvent = null;
}
componentDidMount() {
// 进入页面使手机音量按键失效
NativeModules.KeyEventLister.audioSwitch(true); // 拦截手机音量按键事件
// 编写自己的按键事件
this.keyEvent = DeviceEventEmitter.addListener('keyup', (e) => {
if (e.keyCode === 24) {
// 音量增加键
} else if () {
// 音量减小键
}
console.log(e.keyCode)
})
}
componentWillUnmount() {
// 恢复手机音量按键原本功能
NativeModules.KeyEventLister.audioSwitch(false); // 取消拦截手机音量按键事件
if (this.keyEvent) {
// 移除事件监听
this.keyEvent.remove();
}
}
render() {
return (
<View></View>
)
}
}