0

我最近在做一个项目。这个想法是制作一个蓝牙扬声器,它在扬声器本身具有播放控制,如暂停、播放、下一首歌曲。扬声器将通过蓝牙连接到手机。最终我想实现我在通过蓝牙连接到扬声器的手机上播放的歌曲的按钮控制(在扬声器上)。

我能够通过蓝牙将扬声器连接到手机并播放歌曲,但最大的挑战是我无法从扬声器端暂停或转发手机上的播放列表。我的理解是扬声器能够接收来自手机的信号来播放歌曲,但是我如何从扬声器向手机发送命令(如通过物理按钮的下一首歌曲)(通过像 arduino 这样的微控制器)。我希望我能很好地说明我的情况。我遇到了一些想法,比如有多个蓝牙配对、我将使用的 BT 模块的自定义编程等。

我对所有可以做到这一点的方式持开放态度,如果有人能向我推荐合适的 BT 模块和微控制器,我将不胜感激。

4

1 回答 1

0

关于BT模块,我建议你使用HC-05。对于 MCU,Arduino 不能用来播放音乐……所以你应该选择 Rasberry,但我不确定。还有我没用过...

如果你需要一些类似的代码,我为温室设计了一个应用程序,它可以显示温室内的温度、湿度和光线。

如果您想按顺序阅读这些课程:gitHub。但我也必须发布代码:也许我可以每天删除回购

BLTSocket 类:

public class BLTSocket extends Service {

private static final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static boolean isBtConnected = false;
private static BluetoothAdapter adapter = null;
private static BluetoothSocket socket = null;
private static InputStream is = null;
private static OutputStream os = null;

public BLTSocket(){

}

/**
 * Constructor called when a bluetooth device has been clicked in the layout
 * If the phone's bluetooth socket has not already connected , it tries to initialize
 * the new connection with the one clicked.
 * Get the stream and set @isBtConnected as true
 *
 * @param address - MAC address of the bluetooth device
 */
public BLTSocket(String address){
    if (!isBtConnected || !socket.isConnected()) {
        try {
            adapter = BluetoothAdapter.getDefaultAdapter();
            BluetoothDevice device = adapter.getRemoteDevice(address);
            socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
            socket.connect();
            is = socket.getInputStream();
            os = socket.getOutputStream();
            isBtConnected = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@Override
public void onCreate() {
    HandlerThread handlerThread = new HandlerThread("SURVEYS_SERVICE", Process.THREAD_PRIORITY_BACKGROUND);
    handlerThread.start();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    survey();
    return START_STICKY;
}

/**
 * This handler keeps updating the three surveys reading their current value
 * from the bluetooth module's input stream.
 * Set the the circular progress bar and the own text view below as the relative value
 */
Handler handler = new Handler();
Runnable runnable;
private void survey() {

    runnable = new Runnable() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void run() {
            byte[] survey = new byte[12];
            try {
                /*
                    Once got the current values of the three surveys,
                    it sets the relative progress bar and the text view
                 */
                if(is.read(survey) > 0){
                    for(int i = 0; i < 3; i++){
                        MainActivity.getProgressBars()[i].setProgress(survey[i]);
                        MainActivity.getTextViews()[i].setText(String.valueOf(survey[i]) + (i == 0 ? "°C" : '%'));
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
            handler.postDelayed(this, 2000);
        }
    };
    runnable.run();

}

/**
 * Called when the user click on the UPDATE SEED button
 * on the popup menu of the ViewSeed layout
 *
 * Send to the HC-05 the new recommended values
 *
 * @param values
 */
public void updateSeed(int[] values){
    try {
        handler.removeCallbacks(runnable);
        for(int value : values) {
            os.write(value);
        }
        os.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        handler.postDelayed(runnable, 2000);
    }
}


@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

/**
 * Close the socket and set @isBtConnected as false when the app is closed or crashes
 */
@Override
public void onDestroy() {
    try {
        this.socket.close();
        this.isBtConnected = false;
    }catch (IOException e) {
        e.printStackTrace();
    }
}

}

BLT活动:

public class BluetoothActivity extends AppCompatActivity {

ActivityBluetoothBinding activityBluetoothBinding;

private BluetoothAdapter adapter;
private Set<BluetoothDevice> pairedDevices;
private ListView listBLTDevice;
private TextView bltTV;

private BluetoothDevice deviceSelected;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    activityBluetoothBinding = DataBindingUtil.setContentView(this, R.layout.activity_bluetooth);
    activityBluetoothBinding.setSettings(MainActivity.loadSettings);
    this.bltTV = findViewById(R.id.bltTV);
    this.listBLTDevice = findViewById(R.id.listBLTDevices);
    setBlt();
}

public static BLTSocket bltSocket;

private void setBlt(){
    this.adapter = BluetoothAdapter.getDefaultAdapter();
    //If the adapter is null, the user's phone hasn't a bluetooth radio
    if(adapter != null){
        if(!adapter.isEnabled()){
            //If the bluetooth is disabled, it asks to the user to enable it
            startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);
        }

        //The bonded devices are those ones which have already been compared
        pairedDevices = adapter.getBondedDevices();
        this.bltTV.setText(pairedDevices.size() + " Devices Found");

        if(pairedDevices.size() > 0){

            /*
             *  Create a new list of strings which every one contains the name of one compared
             *  bluetooth radio. The array list is given to the adapter.
             */
            final ArrayList<String> arrayList = new ArrayList<>();
            for (BluetoothDevice device : pairedDevices){
                arrayList.add(device.getName());
            }
            final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, getListViewLayout(), arrayList);
            this.listBLTDevice.setAdapter(adapter);

            /*
                When an item (string that represents a bluetooth radio) has been clicked,
                its MAC address is given to the BLTSocket constructor, which will set
                the opportune variable, objects and connects our radio with the selected one
             */
            this.listBLTDevice.setOnItemClickListener( (parent, v, pos, id) -> {
                deviceSelected = (BluetoothDevice) pairedDevices.toArray()[pos];
                Toast.makeText(getApplicationContext(), "Device Selected: " + deviceSelected.getName() + "\n" + deviceSelected.getAddress(), Toast.LENGTH_SHORT).show();
                bltSocket = new BLTSocket(deviceSelected.getAddress());
                startService(new Intent(this, BLTSocket.class));
            } );
        }
    }else{
        Toast.makeText(getApplicationContext(), "Seems like your device hasn't any bluetooth adapter...", Toast.LENGTH_SHORT).show();
    }
}

/**
 * Called when setting the ArrayAdapter to chose list layout with the right color of the text
 * If the user has the dark mode enabled, this method returns the white list and vice versa
 *
 * @return the id of the opportune listview layout
 */
private int getListViewLayout() {
    return !MainActivity.loadSettings.isDarkMode() ? R.layout.listview_blacktext_layout : R.layout.listview_whitetext_layout;
}

}

于 2021-02-26T07:16:59.427 回答