1. 程式人生 > >Android通過Bluetooth藍芽傳送手機照片檔案到Windows PC:Java實現

Android通過Bluetooth藍芽傳送手機照片檔案到Windows PC:Java實現

Android通過Bluetooth藍芽傳送手機照片檔案到Windows PC:Java實現

本文在《Android通過藍芽傳送資料到Windows PC電腦:Java實現(連結地址:https://blog.csdn.net/zhangphil/article/details/83146705 )》基礎上改進程式碼,還是用Java實現把Android手機上的一張照片,通過Bluetooth藍芽連線,傳送到Windows PC電腦上,實現上仍區分為Windows電腦端的藍芽伺服器端BluetoothJavaServer:

import java.io.BufferedInputStream;
import java.io.FileOutputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

/**
 * BluetoothJavaServer是藍芽的伺服器端。部署在Windows作業系統(PC電腦上)。 等待手機客戶端或者其他藍芽裝置的連線。
 * 
 * @author fly
 *
 */
public class BluetoothJavaServer {
	// 藍芽伺服器端的UUID必須和手機端的UUID一致。
	// 手機端的UUID需要去掉中間的-分割符。
	private String MY_UUID = "0000110100001000800000805F9B34FB";

	public static void main(String[] args) {
		new BluetoothJavaServer();
	}

	public BluetoothJavaServer() {
		StreamConnectionNotifier mStreamConnectionNotifier = null;

		try {
			mStreamConnectionNotifier = (StreamConnectionNotifier) Connector.open("btspp://localhost:" + MY_UUID);
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			System.out.println("伺服器端開始監聽客戶端連線請求...");
			while (true) {
				StreamConnection connection = mStreamConnectionNotifier.acceptAndOpen();
				System.out.println("接受客戶端連線");

				new ClientThread(connection).start();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 開啟一個執行緒專門從與客戶端藍芽裝置中讀取檔案資料,並把檔案資料儲存到本地。
	 * 
	 * @author fly
	 *
	 */
	private class ClientThread extends Thread {
		private StreamConnection mStreamConnection = null;

		public ClientThread(StreamConnection sc) {
			mStreamConnection = sc;
		}

		@Override
		public void run() {
			try {
				BufferedInputStream bis = new BufferedInputStream(mStreamConnection.openInputStream());

				// 本地建立一個image.jpg檔案接收來自於手機客戶端發來的圖片檔案資料。
				FileOutputStream fos = new FileOutputStream("image.jpg");

				int c = 0;
				byte[] buffer = new byte[1024];

				System.out.println("開始讀資料...");
				while (true) {
					c = bis.read(buffer);
					if (c == -1) {
						System.out.println("讀取資料結束");
						break;
					} else {
						fos.write(buffer, 0, c);
					}
				}

				fos.flush();

				fos.close();
				bis.close();
				mStreamConnection.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}


Android手機端的藍芽客戶端BluetoothClientActivity:

package zhangphil.test;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Set;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;

public class BluetoothClientActivity extends AppCompatActivity {
    private BluetoothAdapter mBluetoothAdapter;

    //要連線的目標藍芽裝置(Windows PC電腦的名字)。
    private final String TARGET_DEVICE_NAME = "PHIL-PC";

    private final String TAG = "藍芽除錯";

    //UUID必須是Android藍芽客戶端和Windows PC電腦端一致。
    private final String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB";

    // 通過廣播接收系統傳送出來的藍芽裝置發現通知。
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                String name = device.getName();
                if (name != null)
                    Log.d(TAG, "發現藍芽裝置:" + name);

                if (name != null && name.equals("PHIL-PC")) {
                    Log.d(TAG, "發現目標藍芽裝置,開始執行緒連線");
                    new Thread(new ClientThread(device)).start();

                    // 藍芽搜尋是非常消耗系統資源開銷的過程,一旦發現了目標感興趣的裝置,可以關閉掃描。
                    mBluetoothAdapter.cancelDiscovery();
                }
            }
        }
    };

    /**
     * 該執行緒往藍芽伺服器端傳送檔案資料。
     */
    private class ClientThread extends Thread {
        private BluetoothDevice device;

        public ClientThread(BluetoothDevice device) {
            this.device = device;
        }

        @Override
        public void run() {
            BluetoothSocket socket;

            try {
                socket = device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID));

                Log.d(TAG, "連線藍芽服務端...");
                socket.connect();
                Log.d(TAG, "連線建立.");

                // 開始往伺服器端傳送資料。
                Log.d(TAG, "開始往藍芽伺服器傳送資料...");
                sendDataToServer(socket);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void sendDataToServer(BluetoothSocket socket) {
            try {
                FileInputStream fis = new FileInputStream(getFile());
                BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

                byte[] buffer = new byte[1024];
                int c;
                while (true) {
                    c = fis.read(buffer);
                    if (c == -1) {
                        Log.d(TAG, "讀取結束");
                        break;
                    } else {
                        bos.write(buffer, 0, c);
                    }
                }

                bos.flush();

                fis.close();
                bos.close();

                Log.d(TAG, "傳送檔案成功");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 發給給藍芽伺服器的檔案。
     * 本例傳送一張位於儲存器根目錄下名為 image.jpg 的照片。
     *
     * @return
     */
    private File getFile() {
        File root = Environment.getExternalStorageDirectory();
        File file = new File(root, "image.jpg");
        return file;
    }

    /**
     * 獲得和當前Android藍芽已經配對的藍芽裝置。
     *
     * @return
     */
    private BluetoothDevice getPairedDevices() {
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices != null && pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                // 把已經取得配對的藍芽裝置名字和地址打印出來。
                Log.d(TAG, device.getName() + " : " + device.getAddress());

                //如果已經發現目標藍芽裝置和Android藍芽已經配對,則直接返回。
                if (TextUtils.equals(TARGET_DEVICE_NAME, device.getName())) {
                    Log.d(TAG, "已配對目標裝置 -> " + TARGET_DEVICE_NAME);
                    return device;
                }
            }
        }

        return null;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        BluetoothDevice device = getPairedDevices();
        if (device == null) {
            // 註冊廣播接收器。
            // 接收系統傳送的藍芽發現通知事件。
            IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
            registerReceiver(mBroadcastReceiver, filter);

            if (mBluetoothAdapter.startDiscovery()) {
                Log.d(TAG, "搜尋藍芽裝置...");
            }
        } else {
            new ClientThread(device).start();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBroadcastReceiver);
    }
}


本例出於簡單演示功能的目的,省去了Android客戶端選擇檔案的程式碼實現,事先作為測試檔案,先在Android手機的儲存器根目錄放置一張名為image.jpg的圖片。
務必保證Windows電腦和Android手機上的藍芽均處於開啟狀態。然後先啟動伺服器端程式,再啟動Android手機客戶端程式。
Windows電腦端輸出:


Android studio的logcat輸出: