Android onKey...活动中未调用事件

问题描述 投票:0回答:1

我正在开发一个包含语音通话的项目,但存在一些问题,即我无法在通话时更改音频级别。

项目正在React Native 0.64.2上运行

我尝试用 AudioManager 听硬件按钮来更改音频。但这里的问题是,当用户尝试按住音量按钮时, onKeyDown 永远不会被调用,它仅在未通话时被调用。有谁知道问题是什么。

因为其他人很难测试,当我执行代码并按下音量按钮时,短时间和长时间会发生什么:

onKey... listeners with logs in ReactActivity/AppCompatActivity

Result of logs

为了接管音频,我创建了自己的包,这样我就可以设置当时需要的音频通道。 (我将其链接到项目的 MainActivity,因此通常会执行硬件按下(根据我的说法))

模块:

package be.idealsystems.audioTakeover;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.Map;
import java.util.HashMap;
import android.media.AudioManager;
import java.util.Arrays;
import java.lang.Integer;
import android.util.Log;

public class RNAudioTakeoverModule extends ReactContextBaseJavaModule {
  private static Integer channel = AudioManager.STREAM_MUSIC;

  public RNAudioTakeoverModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }

  @Override
  public String getName() {
    return "RNAudioTakeover";
  }

  public static Integer get() {
    return channel;
  }

  @ReactMethod
  public static void set(Integer value) {
    Integer[] existingStreams = {
      AudioManager.STREAM_ACCESSIBILITY,
      AudioManager.STREAM_ALARM,
      AudioManager.STREAM_DTMF,
      AudioManager.STREAM_MUSIC,
      AudioManager.STREAM_NOTIFICATION,
      AudioManager.STREAM_RING,
      AudioManager.STREAM_SYSTEM,
      AudioManager.STREAM_VOICE_CALL,
      AudioManager.USE_DEFAULT_STREAM_TYPE
    };

    try {
      if (value == (Integer)value && Arrays.asList(existingStreams).contains(value)) {
        channel = value;
      } else {
        channel = AudioManager.STREAM_MUSIC;
      }
    } catch (Exception e) {
        channel = AudioManager.STREAM_MUSIC;
    }
  }
}

包装:

package be.idealsystems.audioTakeover;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class RNAudioTakeoverPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
      return Arrays.<NativeModule>asList(new RNAudioTakeoverModule(reactContext));
    }

    public List<Class<? extends JavaScriptModule>> createJSModules() {
      return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
      return Collections.emptyList();
    }
}

主要活动:

package be.idealsystems.mc.purecloud;

import android.os.SystemClock;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import android.view.KeyEvent;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.graphics.Color;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
import android.content.res.Configuration;
import android.view.WindowManager.LayoutParams;
import java.lang.Integer;

//DSL
import android.view.WindowManager;
import io.wazo.callkeep.RNCallKeepModule; 
import com.overlaypermission.OverlayPermissionPackage;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import android.content.res.Configuration;
import android.content.Intent;
import android.util.Log;
import android.net.Uri;
import be.idealsystems.hideScreenshot.HideScreenshotModule;
import be.idealsystems.audioTakeover.RNAudioTakeoverModule;
import android.media.AudioManager;

public class MainActivity extends ReactActivity {
  private static final String DEFAULT_CHANNEL = "DEFAULT";
  private static final String SILENT_CHANNEL = "SILENT";
  private static final String TEL = "tel";
  public Bundle mInitialProps = null;
  private AudioManager audio;

  /**
   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "Testing";
  }

  @Override
  public void invokeDefaultOnBackPressed() {
    moveTaskToBack(true);
  }

  @Override
  protected ReactActivityDelegate createReactActivityDelegate() {
      return new ReactActivityDelegate(this, getMainComponentName()) {
          @Override
          protected Bundle getLaunchOptions() {
              return mInitialProps;
          }
      };
  }

  @Override
  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
      super.onRequestPermissionsResult(requestCode, permissions, grantResults);
      switch (requestCode) {
          case RNCallKeepModule.REQUEST_READ_PHONE_STATE:
              RNCallKeepModule.onRequestPermissionsResult(requestCode, permissions, grantResults);
              break;
      }
  }

  private void sendEvent(ReactContext reactContext, String eventName, WritableMap params) {
    try{
      reactContext
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
        .emit(eventName, params);
    }
    catch(Exception e){
      Log.d("TEST","ERROR "+ e.getMessage());
    }
  }

  @Override
  protected void onPause() {
      super.onPause();
      if (HideScreenshotModule.get()) {
          getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
      }
  }

  @Override
  protected void onResume() {
      super.onResume();
      if (HideScreenshotModule.get()) {
          getWindow().clearFlags(LayoutParams.FLAG_SECURE);
      }
  }

  @Override
  public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (HideScreenshotModule.get()) {
      if (hasFocus) {
        getWindow().clearFlags(LayoutParams.FLAG_SECURE);
      } else {
        getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
      }
    }
  }
  
  @Override
  public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
      String action = intent.getAction();
      Uri data = intent.getData();
      String stringUri="";
      if (data!=null){
      stringUri = data.toString();
        if (stringUri.contains(TEL)) {
            WritableMap idData = Arguments.createMap();
            
            idData.putString("tel", stringUri);
            sendEvent(getReactInstanceManager().getCurrentReactContext(), "INCOMINGTELFROMOUTSIDEMC", idData);
        }
      }
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    getReactInstanceManager().onConfigurationChanged(this, newConfig);
  }

  // needed for react-native-screens
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);

    //DSL
    mInitialProps = new Bundle();
    Uri test = getIntent().getData();
    String stringUri="";
    if (test!=null)
    stringUri = test.toString();
    if (stringUri.contains(TEL)) {
      mInitialProps.putString(TEL, stringUri);
    }
    audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

    //END DSL

    if (Build.VERSION.SDK_INT >= 26) {
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        createDefaultNotificationChannel(mNotificationManager);
      //  createSilentNotificationChannel(mNotificationManager);
    }

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
      | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
  }

  @Override
  public boolean onKeyShortcut(int keyCode, KeyEvent event) {
    Log.e("@YANNICK", "KEY SHORTCUT " + keyCode);
    return true;
  }

  @Override
  public boolean onKeyUp(int keyCode, KeyEvent event) {
    Log.e("@YANNICK", "KEY UP " + keyCode);
    return true;
  }

  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    Log.e("@YANNICK", "KEY DOWN " + keyCode);
    return true;
  }

  @Override
  public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
    Log.e("@YANNICK", "KEY MULTIPLE " + keyCode + " " + ((Integer)repeatCount).toString());
    return true;
  }

  @Override
  public boolean onKeyLongPress(int keyCode, KeyEvent event) {
    Log.e("@YANNICK", "KEY LONG " + keyCode);
    return true;
  }

  // This works, but executes like keyUp (only once every press)
  /*@Override
  public boolean dispatchKeyEvent(KeyEvent event) {
    int action = event.getAction();
    int keyCode = event.getKeyCode();
  
    Log.e("@YANNICK", "KEY EVENT " + keyCode);

    switch (keyCode) {
      case KeyEvent.KEYCODE_VOLUME_UP:
        audio.adjustStreamVolume(RNAudioTakeoverModule.get(), AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
        return true;
      case KeyEvent.KEYCODE_VOLUME_DOWN:
        audio.adjustStreamVolume(RNAudioTakeoverModule.get(), AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
        return true;
      default:
        return super.dispatchKeyEvent(event);
      }
  }*/
  
  private void createDefaultNotificationChannel(NotificationManager mNotificationManager) {
    NotificationChannel defaultChannel = new NotificationChannel(
        DEFAULT_CHANNEL, 
        "Default channel",
        NotificationManager.IMPORTANCE_HIGH
    );

    defaultChannel.setLightColor(Color.GREEN);
    defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
    mNotificationManager.createNotificationChannel(defaultChannel);
  }

  private void createSilentNotificationChannel(NotificationManager mNotificationManager) {
      NotificationChannel silentChannel = new NotificationChannel(
          SILENT_CHANNEL,
          "Silent channel",
          NotificationManager.IMPORTANCE_HIGH
      );
      silentChannel.setSound(null, null);
      silentChannel.enableLights(false);
      silentChannel.setVibrationPattern(null);
      silentChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
      mNotificationManager.createNotificationChannel(silentChannel);
  }
}
android react-native audio android-activity
1个回答
0
投票

来自简短的文档。

当释放按键且未由活动内的任何视图处理时调用。

可能压力由另一个活动元素处理,或者 我怀疑您在通话期间使用蓝牙连接(例如,使用耳机),那么按下将由蓝牙连接处理。

© www.soinside.com 2019 - 2024. All rights reserved.