Java 在智能手机上播放通过蓝牙从SensorTile(STEVAL-STLKT01V1)接收的音频

Java 在智能手机上播放通过蓝牙从SensorTile(STEVAL-STLKT01V1)接收的音频,java,android,bluetooth,audio-streaming,stm32,Java,Android,Bluetooth,Audio Streaming,Stm32,我正在制作一个应用程序,可以播放通过蓝牙从带有传感器(包括麦克风)的电路板接收到的音频。 在音频功能的“活动”中有两个按钮,允许您以流模式开始播放音频并停止播放。不幸的是,目前它不能像我所希望的那样工作。 问题是audioSample是空的,所以我无法进入onUpdate方法并从样本中提取音频 更改:侦听器更改,添加一个按钮以禁用音频 以下是与活动相关的代码: package com.st.BlueSTSDK.Example; import android.content.Context; i

我正在制作一个应用程序,可以播放通过蓝牙从带有传感器(包括麦克风)的电路板接收到的音频。 在音频功能的“活动”中有两个按钮,允许您以流模式开始播放音频并停止播放。不幸的是,目前它不能像我所希望的那样工作。 问题是audioSample是空的,所以我无法进入onUpdate方法并从样本中提取音频

更改:侦听器更改,添加一个按钮以禁用音频

以下是与活动相关的代码:

package com.st.BlueSTSDK.Example;

import android.content.Context;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;

import com.st.BlueSTSDK.Feature;
import com.st.BlueSTSDK.Features.FeatureAudioADPCM;
import com.st.BlueSTSDK.Features.FeatureAudioADPCMSync;
import com.st.BlueSTSDK.Manager;
import com.st.BlueSTSDK.Node;
import com.st.BlueSTSDK.Utils.BVAudioSyncManager;

import java.util.List;

/**
 * Created by Cesare on 09/06/2017.
 */

public class FeatureAudioActivity extends AppCompatActivity {

    /**
     *   Node that will show the data
     */
    private Node mNode;

    /** fragment used for keep the connection open */
    private NodeContainerFragment mNodeContainer;

    //  Feature on which to apply the listener
    private FeatureAudioADPCM mAudio;

    // feature where we read the audio sync values
    private FeatureAudioADPCMSync mAudioSync;

    // The sampling rate
    private static final int SAMPLE_RATE = 8000;

    // raw audio
    private short audioSample[];

    // audio manager
    private static final int AUDIO_STREAM = AudioManager.STREAM_MUSIC;

    //  Audio track builder
    private AudioTrack mAudioTrack;

    //object containing the sync data needed in a ADPCM stream decoding
    private BVAudioSyncManager mBVAudioSyncManager = new BVAudioSyncManager();


    private final static String NODE_FRAGMENT =   FeatureAudioActivity.class.getCanonicalName() + "" +
        ".NODE_FRAGMENT";
    private final static String NODE_TAG = FeatureAudioActivity.class.getCanonicalName() + "" +
        ".NODE_TAG";



    /**
     * create an intent for start the activity that will log the information from the node
     *
     * @param c    context used for create the intent
     * @param node note that will be used by the activity
     * @return intent for start this activity
     */
    public static Intent getStartIntent(Context c, @NonNull Node node) {
        Intent i = new Intent(c, FeatureAudioActivity.class);
        i.putExtra(NODE_TAG, node.getTag());
        i.putExtras(NodeContainerFragment.prepareArguments(node));
        return i;
    }

    /**
     * listener for the audio feature, it will updates the audio values
     */
    public final Feature.FeatureListener mAudioListener = new Feature.FeatureListener() {

        @Override
        public void onUpdate(final Feature f, final Feature.Sample sample) {
            audioSample = FeatureAudioADPCM.getAudio(sample);
        }

    };

    /**
     * listener for the audioSync feature, it will update the synchronism values
     */
    public final Feature.FeatureListener mAudioSyncListener = new Feature.FeatureListener() {
        @Override
        public void onUpdate(Feature f, final Feature.Sample sample) {
            if(mBVAudioSyncManager!=null){
                mBVAudioSyncManager.setSyncParams(sample);
            }
        }
    };

/* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
    private SeekBar mVolumeBar;
    private AudioManager mAudioManager;

    private Button mPlayButton;
    private Button mStopButton;

    private ImageButton mMuteButton;
    private boolean mIsMute = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_feature_audio);

        // find the node.
        String nodeTag = getIntent().getStringExtra(NODE_TAG);
        mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);


        List<Feature> listFeature = mNode.getFeatures();
        for (Feature f : listFeature) {
            if (f.isEnabled() && f.getName().equals("AudioFeature")) {

                mAudio=(FeatureAudioADPCM) f;

            }//if
            if (f.isEnabled() && f.getName().equals("AudioSyncFeature")) {

                mAudioSync=(FeatureAudioADPCMSync) f;

            }//if
        }//for


        //create/recover the NodeContainerFragment
        if (savedInstanceState == null) {
            Intent i = getIntent();
            mNodeContainer = new NodeContainerFragment();
            mNodeContainer.setArguments(i.getExtras());
            getFragmentManager().beginTransaction()
                .add(mNodeContainer, NODE_FRAGMENT).commit();
        } else {
            mNodeContainer = (NodeContainerFragment) getFragmentManager()
                .findFragmentByTag(NODE_FRAGMENT);
        }//if-else



        //builder audio track
        mAudioTrack = new AudioTrack(
                AudioManager.STREAM_MUSIC,
                SAMPLE_RATE,
                AudioFormat.CHANNEL_OUT_MONO,
                AudioFormat.ENCODING_PCM_16BIT,
                FeatureAudioADPCM.AUDIO_PACKAGE_SIZE,
                AudioTrack.MODE_STREAM);





        mPlayButton = (Button) findViewById(R.id.playButton);
        mStopButton = (Button) findViewById(R.id.stopButton);
        mMuteButton = (ImageButton) findViewById(R.id.muteButton);

//        //start speaker phone
//        AudioManager audioManager =  (AudioManager)getSystemService(Context.AUDIO_SERVICE);
//        audioManager.setMode(AudioManager.MODE_IN_CALL);
//        audioManager.setSpeakerphoneOn(true);


        //  When the play button is pressed
        mPlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                mAudioTrack.play();

                /*Write audio data for playback
              @param short : The array that contains the data for playback
              @param int: offset in rawAudio where playback data begins
              @param int: The number of shorts to read in rawAudio after the offset
                */
                mAudioTrack.write(audioSample,0,audioSample.length);
            }
        });

        //When the stop button is pressed
        mStopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                mAudioTrack.stop();
            }
        });

        //When the mute button is pressed
        mMuteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                changeState();
            }
            boolean changeState(){
                mIsMute=!mIsMute;
                if(mIsMute)
                    muteAudio();
                else
                    unMuteAudio();
                return mIsMute;
            }
            private void muteAudio(){
                  mMuteButton.setImageResource(R.drawable.ic_volume_off_black_32dp);
                mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);
                mVolumeBar.setEnabled(false);
            }

            private void unMuteAudio(){
                mMuteButton.setImageResource(R.drawable.ic_volume_up_black_32dp);
                mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
            mVolumeBar.setEnabled(true);
            }
        });


        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        initControls();


        mAudioSync.addFeatureListener(mAudioSyncListener);
        mAudio.setAudioSyncManager(mBVAudioSyncManager);
        mAudio.addFeatureListener(mAudioListener);
        mNode.enableNotification(mAudio);



    }

    //   Volume control from SeekBar
    private void initControls()
    {
        try
        {
            mVolumeBar = (SeekBar)findViewById(R.id.volumeValue);
            mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
            mVolumeBar.setMax(mAudioManager
                .getStreamMaxVolume(AudioManager.STREAM_MUSIC));
            mVolumeBar.setProgress(mAudioManager
                .getStreamVolume(AudioManager.STREAM_MUSIC));


            mVolumeBar.setOnSeekBarChangeListener(new  SeekBar.OnSeekBarChangeListener()
            {
                @Override
                public void onStopTrackingTouch(SeekBar arg0)
                {
                }

                @Override
                public void onStartTrackingTouch(SeekBar arg0)
                {
                }

                @Override
                public void onProgressChanged(SeekBar arg0, int progress, boolean arg2)
                {
                    mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
                        progress, 0);
                }
            });
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * if we have to leave this activity, we force to keep the connection open, since we go back
     * in the {@link FeatureListActivity}
     */
     @Override
     public void onBackPressed() {
        mNodeContainer.keepConnectionOpen(true);
        super.onBackPressed();
     }//onBackPressed


}
package com.st.BlueSTSDK.Example;
导入android.content.Context;
导入android.content.Intent;
导入android.media.AudioFormat;
导入android.media.AudioManager;
导入android.media.AudioTrack;
导入android.os.Bundle;
导入android.support.annotation.NonNull;
导入android.support.v7.app.AppActivity;
导入android.view.view;
导入android.widget.Button;
导入android.widget.ImageButton;
导入android.widget.SeekBar;
导入com.st.BlueSTSDK.Feature;
导入com.st.BlueSTSDK.Features.FeatureAudioADPCM;
导入com.st.BlueSTSDK.Features.FeatureAudioADPCMSync;
导入com.st.BlueSTSDK.Manager;
导入com.st.BlueSTSDK.Node;
导入com.st.BlueSTSDK.Utils.BVAudioSyncManager;
导入java.util.List;
/**
*由Cesare于2017年6月9日创建。
*/
公共类功能AudioActivity扩展了AppCompatActivity{
/**
*将显示数据的节点
*/
私有节点mNode;
/**用于保持连接打开的片段*/
私有节点容器片段mNodeContainer;
//应用侦听器的功能
私人特辑Adpcm mAudio;
//我们读取音频同步值的功能
专用功能AudioADPCMSync mAudioSync;
//抽样率
私有静态最终整数抽样率=8000;
//原始音频
私人短音频样本[];
//音频管理器
私有静态最终int AUDIO\u STREAM=AudioManager.STREAM\u MUSIC;
//音轨生成器
私人音轨;
//对象,该对象包含ADPCM流解码所需的同步数据
私有BVAudioSyncManager mBVAudioSyncManager=新BVAudioSyncManager();
私有最终静态字符串节点_FRAGMENT=FeatureAudioActivity.class.getCanonicalName()+“”+
“.NODE_片段”;
私有最终静态字符串节点_TAG=FeatureAudioActivity.class.getCanonicalName()+“”+
“.NODE_标记”;
/**
*创建启动活动的意图,该活动将记录来自节点的信息
*
*@param c上下文用于创建意图
*@param节点注释将由活动使用
*@返回开始此活动的意图
*/
公共静态意图GetStartEnt(上下文c,@NonNull节点){
意图i=新意图(c,FeatureAudioActivity.class);
i、 putExtra(NODE_标记,NODE.getTag());
i、 putExtras(NodeContainerFragment.prepareArguments(node));
返回i;
}
/**
*侦听器对于音频功能,它将更新音频值
*/
public final Feature.FeatureListener MaudoListener=新功能。FeatureListener(){
@凌驾
公共void onUpdate(最终特征f,最终特征.示例){
audioSample=FeatureAudioADPCM.getAudio(示例);
}
};
/**
*对于audioSync功能的侦听器,它将更新同步值
*/
public final Feature.FeatureListener mAudioSyncListener=新功能。FeatureListener(){
@凌驾
公共void onUpdate(功能f,最终功能。示例){
if(mBVAudioSyncManager!=null){
mBVAudioSyncManager.setSyncParams(示例);
}
}
};
/* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
私人SeekBar mVolumeBar;
私人音频经理;
私人按钮;
私人按钮mStopButton;
私有图像按钮mmutebuton;
私有布尔mIsMute=false;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u feature\u audio);
//找到节点。
字符串nodeTag=getIntent().getStringExtra(节点标记);
mNode=Manager.getSharedInstance().getNodeWithTag(nodeTag);
List listFeature=mNode.getFeatures();
用于(功能f:listFeature){
如果(f.isEnabled()&&f.getName().equals(“AudioFeature”)){
mAudio=(FeatureAudioADPCM)f;
}//如果
如果(f.isEnabled()&&f.getName().equals(“AudioSyncFeature”)){
mAudioSync=(FeatureAudioADPCMSync)f;
}//如果
}//为了
//创建/恢复NodeContainerFragment
如果(savedInstanceState==null){
Intent i=getIntent();
mNodeContainer=new NodeContainerFragment();
setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer,节点_片段).commit();
}否则{
mNodeContainer=(NodeContainerFragment)getFragmentManager()
.findFragmentByTag(节点\片段);
}//否则
//建设者音轨
mAudioTrack=新的音频曲目(
AudioManager.STREAM_音乐,
抽样率,
AudioFormat.CHANNEL\u OUT\u MONO,
AudioFormat.ENCODING_PCM_16位,
功能AudioADPCM.AUDIO\u包装尺寸,
音频跟踪模式(音频流);
mPlayButton=(按钮)findviewbyd(R.id.playButton);
mStopButton=(按钮)findviewbyd(R.id.stopButton);
mMuteButton=(ImageButton)findViewById(R.id.muteButton);
////启动扬声器电话
//音频管理器音频管理
package com.st.BlueSTSDK.Example;

import android.content.Context;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.SeekBar;

import com.st.BlueSTSDK.Feature;
import com.st.BlueSTSDK.Features.FeatureAudioADPCM;
import com.st.BlueSTSDK.Features.FeatureAudioADPCMSync;
import com.st.BlueSTSDK.Manager;
import com.st.BlueSTSDK.Node;
import com.st.BlueSTSDK.Utils.BVAudioSyncManager;

import java.util.List;


public class FeatureAudioActivity extends AppCompatActivity {

/**
 *   Node that will show the data
 */
private Node mNode;

/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;

//  Feature on which to apply the listener
private FeatureAudioADPCM mAudio;

// feature where we read the audio sync values
private FeatureAudioADPCMSync mAudioSync;

// The sampling rate
private static final int SAMPLE_RATE = 8000;

// audio manager
private static final int AUDIO_STREAM = AudioManager.STREAM_MUSIC;

//  Audio track builder
private AudioTrack mAudioTrack;

//object containing the sync data needed in a ADPCM stream decoding
private BVAudioSyncManager mBVAudioSyncManager = new BVAudioSyncManager();


private final static String NODE_FRAGMENT =   FeatureAudioActivity.class.getCanonicalName() + "" +
        ".NODE_FRAGMENT";
private final static String NODE_TAG = FeatureAudioActivity.class.getCanonicalName() + "" +
        ".NODE_TAG";



/**
 * create an intent for start the activity that will log the information from the node
 *
 * @param c    context used for create the intent
 * @param node note that will be used by the activity
 * @return intent for start this activity
 */
public static Intent getStartIntent(Context c, @NonNull Node node) {
    Intent i = new Intent(c, FeatureAudioActivity.class);
    i.putExtra(NODE_TAG, node.getTag());
    i.putExtras(NodeContainerFragment.prepareArguments(node));
    return i;
}

/**
 * listener for the audio feature, it will updates the audio values
 */
public final Feature.FeatureListener mAudioListener = new Feature.FeatureListener() {

    @Override
    public void onUpdate(final Feature f, final Feature.Sample sample) {
        short audioSample[] = FeatureAudioADPCM.getAudio(sample);

          /*Write audio data for playback
          @param short : The array that contains the data for playback
          @param int: offset in rawAudio where playback data begins
          @param int: The number of shorts to read in rawAudio after the offset
            */
        mAudioTrack.write(audioSample,0,audioSample.length);
    }

};

/**
 * listener for the audioSync feature, it will update the synchronism values
 */
public final Feature.FeatureListener mAudioSyncListener = new Feature.FeatureListener() {
    @Override
    public void onUpdate(Feature f, final Feature.Sample sample) {
        if(mBVAudioSyncManager!=null){
            mBVAudioSyncManager.setSyncParams(sample);
        }
    }
};

/* ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */
private SeekBar mVolumeBar;
private AudioManager mAudioManager;

private Button mPlayButton;
private Button mStopButton;

private ImageButton mMuteButton;
private boolean mIsMute = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_feature_audio);

    // find the node.
    String nodeTag = getIntent().getStringExtra(NODE_TAG);
    mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);


    List<Feature> listFeature = mNode.getFeatures();
    for (Feature f : listFeature) {
        if (f.isEnabled() && f.getName().equals("AudioFeature")) {

            mAudio=(FeatureAudioADPCM) f;

        }//if
        if (f.isEnabled() && f.getName().equals("AudioSyncFeature")) {

            mAudioSync=(FeatureAudioADPCMSync) f;

        }//if
    }//for


    //create/recover the NodeContainerFragment
    if (savedInstanceState == null) {
        Intent i = getIntent();
        mNodeContainer = new NodeContainerFragment();
        mNodeContainer.setArguments(i.getExtras());
        getFragmentManager().beginTransaction()
                .add(mNodeContainer, NODE_FRAGMENT).commit();
    } else {
        mNodeContainer = (NodeContainerFragment) getFragmentManager()
                .findFragmentByTag(NODE_FRAGMENT);
    }//if-else



    //builder audio track
    mAudioTrack = new AudioTrack(
            AudioManager.STREAM_MUSIC,
            SAMPLE_RATE,
            AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT,
            FeatureAudioADPCM.AUDIO_PACKAGE_SIZE,
            AudioTrack.MODE_STREAM);



    mPlayButton = (Button) findViewById(R.id.playButton);
    mStopButton = (Button) findViewById(R.id.stopButton);
    mMuteButton = (ImageButton) findViewById(R.id.muteButton);



    //  When the play button is pressed
    mPlayButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if(!mIsMute){
                mAudioTrack.play();
                mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
            }

        }
    });

    //When the stop button is pressed
    mStopButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            stopAudioTrack();
            mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);

        }
    });

    //When the mute button is pressed
    mMuteButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            changeState();
        }
        boolean changeState(){
            mIsMute=!mIsMute;
            if(mIsMute)
                muteAudio();
            else
                unMuteAudio();
            return mIsMute;
        }
        private void muteAudio(){
            mMuteButton.setImageResource(R.drawable.ic_volume_off_black_32dp);
            mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);
            mVolumeBar.setEnabled(false);
        }

        private void unMuteAudio(){
            mMuteButton.setImageResource(R.drawable.ic_volume_up_black_32dp);
            mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
            mVolumeBar.setEnabled(true);
        }
    });

    //enable control volume
    setVolumeControlStream(AudioManager.STREAM_MUSIC);
    initControls();


}

@Override
public void onResume(){
    super.onResume();
    // enable needed notification
    if(mAudio!=null && mAudioSync!=null) {
        mAudio.addFeatureListener(mAudioListener);
        mBVAudioSyncManager.reinitResetFlag();
        mAudio.setAudioSyncManager(mBVAudioSyncManager);
        mNode.enableNotification(mAudio);
        mAudioSync.addFeatureListener(mAudioSyncListener);
        mNode.enableNotification(mAudioSync);
    }
}

@Override
public void onPause(){
    super.onPause();
    // disable needed notification
    if(mAudio!=null) {
        mAudio.removeFeatureListener(mAudioListener);
        mNode.disableNotification(mAudio);
    }
    if(mAudioSync!=null) {
        mAudioSync.removeFeatureListener(mAudioSyncListener);
        mNode.disableNotification(mAudioSync);
    }
}



private void stopAudioTrack(){
    synchronized(this) {
        mAudioTrack.pause();
        mAudioTrack.flush();
    }
}



//   Volume control from SeekBar
private void initControls()
{
    try
    {
        mVolumeBar = (SeekBar)findViewById(R.id.volumeValue);
        mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
        mVolumeBar.setMax(mAudioManager
                .getStreamMaxVolume(AudioManager.STREAM_MUSIC));
        mVolumeBar.setProgress(mAudioManager
                .getStreamVolume(AudioManager.STREAM_MUSIC));


        mVolumeBar.setOnSeekBarChangeListener(new  SeekBar.OnSeekBarChangeListener()
        {
            @Override
            public void onStopTrackingTouch(SeekBar arg0)
            {
            }

            @Override
            public void onStartTrackingTouch(SeekBar arg0)
            {
            }

            @Override
            public void onProgressChanged(SeekBar arg0, int progress, boolean arg2)
            {
                mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
                        progress, 0);
            }
        });
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

/**
 * if we have to leave this activity, we force to keep the connection open, since we go back
 * in the {@link FeatureListActivity}
 */
@Override
public void onBackPressed() {
    mNodeContainer.keepConnectionOpen(true);
    super.onBackPressed();
}//onBackPressed