Android RecognizerIntent与蓝牙耳机



http://codego.net/554937/

使用Android RecognizerIntent与蓝牙耳机 +

androidbluetooth-蓝牙speech-recognition-发言-承认
下面的编码,以在Android中启动语音识别:
PackageManager pm = getPackageManager();
List<ResolveInfo> activities = pm.queryIntentActivities(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);

if (activities.size() == 0) {
 displayWarning("This device does not support speech recognition");
 return;
}

Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);

startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);

这工作得很好。然而,它似乎并没有接受来自蓝牙耳机配对,而“手机音频”配置文件语音输入。 一,应用程序称为的SOUNDabout率有力的“Media音频”到“ 蓝牙 (单声道)(SCO)”。有了这个程序集,我的语音识别现在可以从我的耳机追踪我的语音输入。 如何RecognizerIntent,并从蓝牙耳机语音输入? 我在API级别16看到有一个新的动作ACTION_VOICE_SEARCH_HANDS_FREE意图形式可供选择。这是太新了,但这样就解决了我的问题呢? 我一定要围绕淤泥在AudioManager类(就像我的SOUNDabout正在做)将音频路由setBluetoothScoOn()或startBluetoothSco()? +
本文地址 :CodeGo.net/554937/ 
width="640" height="60" src="http://cb.baidu.com/ecom?adn=4&at=6&aurl=&cad=1&ccd=24&cec=UTF-8&cfv=14&ch=0&col=zh-CN&conOP=0&cpa=1&dai=5&dis=0&ltr=http%3A%2F%2Fblog.csdn.net%2Flihongyu65085%2Farticle%2Fdetails%2F39827251&ltu=http%3A%2F%2Fcodego.net%2F554937%2F&lunum=6&n=binfenkeji2010_cpr&pcs=1920x949&pis=10000x10000&ps=-1x-1&psr=1920x1080&pss=1920x0&qn=bf42aed2af105fc5&rad=&rs=301&rsi0=640&rsi1=60&rsi5=4&rss0=%23FFFFFF&rss1=%23FFFFFF&rss2=%230000ff&rss3=%23444444&rss4=%23008000&rss5=&rss6=%23e10900&rss7=&scale=&skin=&td_id=9223372032564535439&tn=text_default_640_60&tpr=1412947832520&ts=1&xuanting=0&dtm=BAIDU_DUP2_SETJSONADSLOT&dc=2&di=972677" align="center,center" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true">

------------------------------------------------------------------------------------------------------------------------- 

1.  许可清单
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> 

创建一个内部类 BluetoothHelper extends BluetoothHeadSetUtils 在你的 Activity Service 。报告 mBluetoothHelper 并实例化它 onCreate()
BluetoothHelper mBluetoothHelper;

@Override
public void onCreate()
{ 
  mBluetoothHelper = new BluetoothHelper(this);
} 

@Override
onResume()
{ 
 mBluetoothHelper.start();
}

@Override
onPause()
{
 mBluetoothHelper.stop();
}

// inner class
// BluetoothHeadsetUtils is an abstract class that has
// 4 abstracts methods that need to be implemented.
private class BluetoothHelper extends BluetoothHeadSetUtils
{
 public BluetoothHelper(Context context)
 {
  super(context);
 }

 @Override
 public void onScoAudioDisconnected()
 {
  // Cancel speech recognizer if desired
 }

 @Override
 public void onScoAudioConnected()
 {   
  // Should start speech recognition here if not already started 
 }

 @Override
 public void onHeadsetDisconnected()
 {

 }

 @Override
 public void onHeadsetConnected()
 {

 }
}

蓝牙耳机 与文本语音转换,你需要设置的速度AudioManager类STREAM_VOICE_CALL在拨打电话之前说话。下面的销
protected void speak(String text)
{

 HashMap<String, String> myHashRender = new HashMap<String, String>();

 if (mBluetoothHelper.isOnHeadsetSco())
 {
  myHashRender.put(TextToSpeech.Engine.KEY_PARAM_STREAM, 
   String.valueOf(AudioManager.STREAM_VOICE_CALL));
 }
 mTts.speak(text, TextToSpeech.QUEUE_FLUSH, myHashRender);
}

该BluetoothHeadsetUtils类复制到您的项目。
import java.util.List;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Build;
import android.os.CountDownTimer;
import android.util.Log;

/**
 * This is a utility to detect bluetooth headset connection and establish audio connection
 * for android API >= 8. This includes a work around for API < 11 to detect already connected headset
 * before the application starts. This work around would only fails if Sco audio
 * connection is accepted but the connected device is not a headset.
 * 
 * @author Hoan Nguyen
 *
 */
public abstract class BluetoothHeadsetUtils
{
 private Context mContext;

 private BluetoothAdapter mBluetoothAdapter;
 private BluetoothHeadset mBluetoothHeadset;
 private BluetoothDevice mConnectedHeadset;

 private AudioManager mAudioManager;

 private boolean mIsCountDownOn;
 private boolean mIsStarting;
 private boolean mIsOnHeadsetSco;
 private boolean mIsStarted;

 private static final String TAG = "BluetoothHeadsetUtils"; //$NON-NLS-1$

 /**
  * Constructor
  * @param context
  */
 public BluetoothHeadsetUtils(Context context)
 {
  mContext = context;
  mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
 }

 /**
  * Call this to start BluetoothHeadsetUtils functionalities.
  * @return The return value of startBluetooth() or startBluetooth11()
  */
 public boolean start()
 {
  if (!mIsStarted)
  {
   mIsStarted = true;

   if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
   {
    mIsStarted = startBluetooth();
   }
   else
   {
    mIsStarted = startBluetooth11();
   }
  }

  return mIsStarted;
 }

 /**
  * Should call this on onResume or onDestroy.
  * Unregister broadcast receivers and stop Sco audio connection
  * and cancel count down.
  */
 public void stop()
 {
  if (mIsStarted)
  {
   mIsStarted = false;

   if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
   {
    stopBluetooth();
   }
   else
   {
    stopBluetooth11();
   }
  }
 }

 /**
  * 
  * @return true if audio is connected through headset.
  */
 public boolean isOnHeadsetSco()
 {
  return mIsOnHeadsetSco;
 }

 public abstract void onHeadsetDisconnected();

 public abstract void onHeadsetConnected();

 public abstract void onScoAudioDisconnected();

 public abstract void onScoAudioConnected();

 /**
  * Register for bluetooth headset connection states and Sco audio states.
  * Try to connect to bluetooth headset audio by calling startBluetoothSco(). 
  * This is a work around for API < 11 to detect if a headset is connected before 
  * the application starts.
  * 
  * The official documentation for startBluetoothSco() states
  * 
  * "This method can be used by applications wanting to send and received audio to/from 
  * a bluetooth SCO headset while the phone is not in call."
  * 
  * Does this mean that startBluetoothSco() would fail if the connected bluetooth device
  * is not a headset?
  * 
  * Thus if a call to startBluetoothSco() is successful, i.e mBroadcastReceiver will receive
  * an ACTION_SCO_AUDIO_STATE_CHANGED with intent extra SCO_AUDIO_STATE_CONNECTED, then
  * we assume that a headset is connected.
  * 
  * @return false if device does not support bluetooth or current platform does not supports
  *    use of SCO for off call.
  */
 @SuppressWarnings("deprecation")
 private boolean startBluetooth()
 {
  Log.d(TAG, "startBluetooth"); //$NON-NLS-1$

  // Device support bluetooth
  if (mBluetoothAdapter != null)
  {  
   if (mAudioManager.isBluetoothScoAvailableOffCall())
   {
    mContext.registerReceiver(mBroadcastReceiver, 
          new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));
    mContext.registerReceiver(mBroadcastReceiver, 
          new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
    mContext.registerReceiver(mBroadcastReceiver, 
          new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));

    // Need to set audio mode to MODE_IN_CALL for call to startBluetoothSco() to succeed.
    mAudioManager.setMode(AudioManager.MODE_IN_CALL);

    mIsCountDownOn = true;
    // mCountDown repeatedly tries to start bluetooth Sco audio connection.
    mCountDown.start();

    // need for audio sco, see mBroadcastReceiver
    mIsStarting = true;

    return true;
   }
  }

  return false;
 }

 /**
  * Register a headset profile listener
  * @return false if device does not support bluetooth or current platform does not supports
  *     use of SCO for off call or error in getting profile proxy.
  */
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 private boolean startBluetooth11()
 {
  Log.d(TAG, "startBluetooth11"); //$NON-NLS-1$

  // Device support bluetooth
  if (mBluetoothAdapter != null)
  {
   if (mAudioManager.isBluetoothScoAvailableOffCall())
   {
    // All the detection and audio connection are done in mHeadsetProfileListener
    if (mBluetoothAdapter.getProfileProxy(mContext, 
             mHeadsetProfileListener, 
             BluetoothProfile.HEADSET))
    {
     return true;
    }
   }
  }

  return false;
 }

 /**
  * API < 11
  * Unregister broadcast receivers and stop Sco audio connection
  * and cancel count down.
  */
 private void stopBluetooth()
 {
  Log.d(TAG, "stopBluetooth"); //$NON-NLS-1$

  if (mIsCountDownOn)
  {
   mIsCountDownOn = false;
   mCountDown.cancel();
  }

  // Need to stop Sco audio connection here when the app
  // change orientation or close with headset still turns on.
  mContext.unregisterReceiver(mBroadcastReceiver);
  mAudioManager.stopBluetoothSco();
  mAudioManager.setMode(AudioManager.MODE_NORMAL);
 }

 /**
  * API >= 11
  * Unregister broadcast receivers and stop Sco audio connection
  * and cancel count down.
  */
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 protected void stopBluetooth11()
 {
  Log.d(TAG, "stopBluetooth11"); //$NON-NLS-1$

  if (mIsCountDownOn)
  {
   mIsCountDownOn = false;
   mCountDown11.cancel();
  }

  if (mBluetoothHeadset != null)
  {
   // Need to call stopVoiceRecognition here when the app
   // change orientation or close with headset still turns on.
   mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);
   mContext.unregisterReceiver(mHeadsetBroadcastReceiver);
   mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
   mBluetoothHeadset = null;
  }
 }

 /**
  * Broadcast receiver for API < 11
  * Handle headset and Sco audio connection states.
  */
 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver()
 {
  @SuppressWarnings({"deprecation", "synthetic-access"})
  @Override
  public void onReceive(Context context, Intent intent)
  {
   String action = intent.getAction();

   if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED))
   {  
    mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    BluetoothClass bluetoothClass = mConnectedHeadset.getBluetoothClass();
    if (bluetoothClass != null)
    {
     // Check if device is a headset. Besides the 2 below, are there other 
     // device classes also qualified as headset?
     int deviceClass = bluetoothClass.getDeviceClass();
     if (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE 
      || deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)
     {
      // start bluetooth Sco audio connection.
      // Calling startBluetoothSco() always returns faIL here, 
      // that why a count down timer is implemented to call
      // startBluetoothSco() in the onTick.
      mAudioManager.setMode(AudioManager.MODE_IN_CALL);
      mIsCountDownOn = true;
      mCountDown.start();

      // override this if you want to do other thing when the device is connected.
      onHeadsetConnected();
     }
    }

    Log.d(TAG, mConnectedHeadset.getName() + " connected"); //$NON-NLS-1$
   }
   else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED))
   {
    Log.d(TAG, "Headset disconnected"); //$NON-NLS-1$

    if (mIsCountDownOn)
    {
     mIsCountDownOn = false;
     mCountDown.cancel();
    }

    mAudioManager.setMode(AudioManager.MODE_NORMAL);

    // override this if you want to do other thing when the device is disconnected.
    onHeadsetDisconnected();
   }
   else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED))
   {
    int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 
            AudioManager.SCO_AUDIO_STATE_ERROR);

    if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED)
    {
     mIsOnHeadsetSco = true;

     if (mIsStarting)
     {
      // When the device is connected before the application starts,
      // ACTION_ACL_CONNECTED will not be received, so call onHeadsetConnected here
      mIsStarting = false;
      onHeadsetConnected();
     }

     if (mIsCountDownOn)
     {
      mIsCountDownOn = false;
      mCountDown.cancel();
     }

     // override this if you want to do other thing when Sco audio is connected.
     onScoAudioConnected();

     Log.d(TAG, "Sco connected"); //$NON-NLS-1$
    }
    else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED)
    {
     Log.d(TAG, "Sco disconnected"); //$NON-NLS-1$

     // Always receive SCO_AUDIO_STATE_DISCONNECTED on call to startBluetooth()
     // which at that stage we do not want to do anything. Thus the if condition.
     if (!mIsStarting)
     {
      mIsOnHeadsetSco = false;

      // Need to call stopBluetoothSco(), otherwise startBluetoothSco()
      // will not be successful.
      mAudioManager.stopBluetoothSco();

      // override this if you want to do other thing when Sco audio is disconnected.
      onScoAudioDisconnected();
     } 
    }
   }
  }
 };

 /**
  * API < 11
  * Try to connect to audio headset in onTick.
  */
 private CountDownTimer mCountDown = new CountDownTimer(10000, 1000)
 {

  @SuppressWarnings("synthetic-access")
  @Override
  public void onTick(long millisUntilFinished)
  {
   // When this call is successful, this count down timer will be canceled.
   mAudioManager.startBluetoothSco();

   Log.d(TAG, "\nonTick start bluetooth Sco"); //$NON-NLS-1$
  }

  @SuppressWarnings("synthetic-access")
  @Override
  public void onFinish()
  {
   // Calls to startBluetoothSco() in onStick are not successful.
   // Should implement something to inform user of this failure
   mIsCountDownOn = false;
   mAudioManager.setMode(AudioManager.MODE_NORMAL);

   Log.d(TAG, "\nonFinish fail to connect to headset audio"); //$NON-NLS-1$
  }
 };

 /**
  * API >= 11
  * Check for already connected headset and if so start audio connection.
  * Register for broadcast of headset and Sco audio connection states.
  */
 private BluetoothProfile.ServiceListener mHeadsetProfileListener = new BluetoothProfile.ServiceListener()
 {

  /**
   * This method is never called, even when we closeProfileProxy on onPause.
   * When or will it ever be called???
   */
  @Override
  public void onServiceDisconnected(int profile)
  {
   Log.d(TAG, "Profile listener onServiceDisconnected"); //$NON-NLS-1$
   stopBluetooth11();
  }

  @SuppressWarnings("synthetic-access")
  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  @Override
  public void onServiceConnected(int profile, BluetoothProfile proxy)
  {
   Log.d(TAG, "Profile listener onServiceConnected"); //$NON-NLS-1$

   // mBluetoothHeadset is just a headset profile, 
   // it does not represent a headset device.
   mBluetoothHeadset = (BluetoothHeadset) proxy;

   // If a headset is connected before this application starts,
   // ACTION_CONNECTION_STATE_CHANGED will not be broadcast. 
   // So we need to check for already connected headset.
   List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
   if (devices.size() > 0)
   {
    // Only one headset can be connected at a time, 
    // so the connected headset is at index 0.
    mConnectedHeadset = devices.get(0);

    onHeadsetConnected();

    // Should not need count down timer, but just in case.
    // See comment below in mHeadsetBroadcastReceiver onReceive()
    mIsCountDownOn = true;
    mCountDown11.start();

    Log.d(TAG, "Start count down"); //$NON-NLS-1$
   }

   // During the active life time of the app, a user may turn on and off the headset.
   // So register for broadcast of connection states.
   mContext.registerReceiver(mHeadsetBroadcastReceiver, 
       new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED));
   // Calling startVoiceRecognition does not result in immediate audio connection.
   // So register for broadcast of audio connection states. This broadcast will
   // only be sent if startVoiceRecognition returns true.
   mContext.registerReceiver(mHeadsetBroadcastReceiver, 
       new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
  }
 };

 /**
  * API >= 11
  * Handle headset and Sco audio connection states.
  */
 private BroadcastReceiver mHeadsetBroadcastReceiver = new BroadcastReceiver()
 {

  @SuppressWarnings("synthetic-access")
  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  @Override
  public void onReceive(Context context, Intent intent)
  {
   String action = intent.getAction();
   int state;
   if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED))
   {
    state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, 
           BluetoothHeadset.STATE_DISCONNECTED);
    Log.d(TAG, "\nAction = " + action + "\nState = " + state); //$NON-NLS-1$ //$NON-NLS-2$
    if (state == BluetoothHeadset.STATE_CONNECTED)
    {
     mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

     // Calling startVoiceRecognition always returns false here, 
     // that why a count down timer is implemented to call
     // startVoiceRecognition in the onTick.
     mIsCountDownOn = true;
     mCountDown11.start();

     // override this if you want to do other thing when the device is connected.
     onHeadsetConnected();

     Log.d(TAG, "Start count down"); //$NON-NLS-1$
    }
    else if (state == BluetoothHeadset.STATE_DISCONNECTED)
    {
     // Calling stopVoiceRecognition always returns false here
     // as it should since the headset is no longer connected.
     if (mIsCountDownOn)
     {
      mIsCountDownOn = false;
      mCountDown11.cancel();
     }
     mConnectedHeadset = null;

     // override this if you want to do other thing when the device is disconnected.
     onHeadsetDisconnected();

     Log.d(TAG, "Headset disconnected"); //$NON-NLS-1$
    }
   }
   else // audio
   {
    state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
    Log.d(TAG, "\nAction = " + action + "\nState = " + state); //$NON-NLS-1$ //$NON-NLS-2$
    if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED)
    {
     Log.d(TAG, "\nHeadset audio connected"); //$NON-NLS-1$

     mIsOnHeadsetSco = true;

     if (mIsCountDownOn)
     {
      mIsCountDownOn = false;
      mCountDown11.cancel();
     }

     // override this if you want to do other thing when headset audio is connected.
     onScoAudioConnected();
    }
    else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED)
    {
     mIsOnHeadsetSco = false;

     // The headset audio is disconnected, but calling
     // stopVoiceRecognition always returns true here.
     mBluetoothHeadset.stopVoiceRecognition(mConnectedHeadset);

     // override this if you want to do other thing when headset audio is disconnected.
     onScoAudioDisconnected();

     Log.d(TAG, "Headset audio disconnected"); //$NON-NLS-1$
    }
   } 
  }
 };

 /**
  * API >= 11
  * Try to connect to audio headset in onTick.
  */
 private CountDownTimer mCountDown11 = new CountDownTimer(10000, 1000)
 {
  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
  @SuppressWarnings("synthetic-access")
  @Override
  public void onTick(long millisUntilFinished)
  {
   // First stick calls always returns false. The second stick
   // always returns true if the countDownInterval is set to 1000.
   // It is somewhere in between 500 to a 1000.
   mBluetoothHeadset.startVoiceRecognition(mConnectedHeadset);

   Log.d(TAG, "onTick startVoiceRecognition"); //$NON-NLS-1$
  }

  @SuppressWarnings("synthetic-access")
  @Override
  public void onFinish()
  {
   // Calls to startVoiceRecognition in onStick are not successful.
   // Should implement something to inform user of this failure
   mIsCountDownOn = false;
   Log.d(TAG, "\nonFinish fail to connect to headset audio"); //$NON-NLS-1$
  }
 };

} 

(2013年4月30日)编辑更改为@TargetApi(Build.VERSION_CODES.HONEYCOMB)必要时。如果你有问题,java.lang.NoClassDefFoundError的API,8或9,只是删除所有的API>=11码。该startBluetoothSco()API适用于所有版本。 + 

2.  尽管蓝牙耳机配对并连接到手机音频配置文件(HF / HS),实际的音频连接(SCO)当呼叫才成立和接受。 为你的应用VR从蓝牙耳机接收语音输入应用程序将不得不建立上海合作组织到VR耳机触发输入, 你需要以下- isBluetoothScoAvailableOffCall检查,如果平台支持此功能, startBluetoothSco和stopBluetoothSco启动上海合作组织的耳机。 + 

3.  我认为,所有你必须改变背面的音频设置为您的应用程序。 如果你推杆以下引脚当你想接收,并通过蓝牙从耳机发出的声音。
 AudioManager audioManager;

audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);

不要忘记恢复以下列方式在手机上正常的设置当你的蓝牙。
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.stopBluetoothSco();
audioManager.setBluetoothScoOn(false);

有需要的权限如下:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

这很容易! + 

4.  startBluetoothSco需要长时间来建立,也就是如果你需要它的语音控制的问题。 有没有快速的方法来 蓝牙 mic来听录音,然后听完之后把它关掉? 如果连接的是对整个那么它是不可能通过流支持A2DP的音频。 密封式的,理想化的世界: 通过支持A2DP八月音频。当它开始监听,SCO蓝牙mic。任何回应又是支持A2DP。 事实上,如果它已经连接-你可以在飞行中通过改变流切换到流调用? DM跳,有没有明显的延迟? +

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值