Android工程搭建
如何区分客户端和服务端?如果设备A连接设备B 那么A就是客户端,B就是服务端。
客户端功能:打开蓝牙/关闭蓝牙/搜索附近蓝牙设备/点击其中一个建立连接
添加权限:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
客户端代码
public class MainActivity extends AppCompatActivity implements OnclickListener {
RecyclerView rv;
BluetoothManager bluetoothManager;
BluetoothAdapter bluetoothAdapter;
ArrayList<BluetoothDevice> list = new ArrayList<>();
MyRvadapter<BluetoothDevice> rvadapter;
BluetoothServerSocket serverSocket;
MapView maps;
ProgressBar pb;
private UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB");
@SuppressLint("HandlerLeak")
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==1000){
int length= (int) msg.obj;
int arg1 = msg.arg1;
pb.setMax(length);
pb.setProgress(arg1);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rv=findViewById(R.id.rv);
pb=findViewById(R.id.pb);
maps=findViewById(R.id.maps);
String[] ss=new String[]{
Manifest.permission.BLUETOOTH,
Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.BLUETOOTH_ADMIN,Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA};
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
for (int i=0;i<ss.length;i++){
int permission = ActivityCompat.checkSelfPermission(this, ss[i]);
if(permission== PackageManager.PERMISSION_DENIED){
requestPermissions(ss,101);
break;
}
}
}
rvadapter = new MyRvadapter<BluetoothDevice>(this, list, R.layout.layout) {
@Override
public void bind(MyRVviewHolder myRVviewHolder, int i) {
myRVviewHolder.gettext(R.id.tv_name,list.get(i).getName());
myRVviewHolder.gettext(R.id.tv_adress,list.get(i).getAddress());
}
};
rvadapter.setListener(this);
bluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
bluetoothAdapter=bluetoothManager.getAdapter();
if(!bluetoothAdapter.isEnabled()){
Intent intent = new Intent();
intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);
intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,200);
startActivityForResult(intent,101);
}
Set<BluetoothDevice> bondedDevices = bluetoothAdapter.getBondedDevices();
list.addAll(bondedDevices);
rvadapter.notifyDataSetChanged();
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(rvadapter);
new Thread(new Runnable() {
@Override
public void run() {
try {
serverSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(bluetoothAdapter.getName(),uuid);
} catch (IOException e) {
e.printStackTrace();
}
while (true){
try {
final BluetoothSocket socket = serverSocket.accept();
new ServiceThread(socket,handler,MainActivity.this).start();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, ""+socket.getRemoteDevice().getName(), Toast.LENGTH_SHORT).show();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
//创建地图
maps.onCreate(savedInstanceState);
}
@Override
protected void onDestroy() {
super.onDestroy();
maps.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
maps.onResume();
}
@Override
protected void onPause() {
super.onPause();
maps.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
maps.onSaveInstanceState(outState);
}
@Override
public void Onclick(int postion) {
BluetoothDevice device = list.get(postion);
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
intent.putExtra("device",device);
startActivity(intent);
}
}
客户端代码
public class Main2Activity extends AppCompatActivity implements View.OnClickListener {
private EditText ed_mess;
private Button btn_text;
private Button btn_pic;
private Button btn_file;
ProgressBar pb1;
String path;
BluetoothDevice device;
private UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB");
LocationManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
Intent intent = getIntent();
device = intent.getParcelableExtra("device");
pb1=findViewById(R.id.pb1);
}
private void initView() {
ed_mess = (EditText) findViewById(R.id.ed_mess);
btn_text = (Button) findViewById(R.id.btn_text);
btn_pic = (Button) findViewById(R.id.btn_pic);
btn_file = (Button) findViewById(R.id.btn_file);
btn_text.setOnClickListener(this);
btn_pic.setOnClickListener(this);
btn_file.setOnClickListener(this);
}
private void into() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 102);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_text:
new Thread(new Runnable() {
@Override
public void run() {
try {
String trim = ed_mess.getText().toString().trim();
BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
socket.connect();
byte[] bytes = trim.getBytes();
socket.getOutputStream().write(("text " + bytes.length).getBytes());
Thread.sleep(20);
socket.getOutputStream().write(bytes);
Log.e("##", bytes.length + "");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
break;
case R.id.btn_pic:
into();
break;
case R.id.btn_file:
Log.e("zzt", "onClick: ");
manager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 200, 1, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
final double longitude = location.getLongitude();//经度
final double latitude = location.getLatitude(); //纬度
Log.e("###1",longitude+" "+latitude+"");
new Thread(new Runnable() {
@Override
public void run() {
try {
BluetoothSocket serviceRecord = device.createInsecureRfcommSocketToServiceRecord(uuid);
serviceRecord.connect();
serviceRecord.getOutputStream().write(("location "+0).getBytes());
Thread.sleep(20);
serviceRecord.getOutputStream().write((longitude+" "+latitude).getBytes());
Log.e("###",longitude+" "+latitude+"");
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
});
break;
}
}
private void submit() {
// validate
String mess = ed_mess.getText().toString().trim();
if (TextUtils.isEmpty(mess)) {
Toast.makeText(this, "mess不能为空", Toast.LENGTH_SHORT).show();
return;
}
// TODO validate success, do something
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 102 && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
Cursor cursor = getContentResolver().query(uri, new String[]{
MediaStore.Images.Media.DATA}, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
}
}
new Thread(new Runnable() {
@Override
public void run() {
BluetoothSocket socket = null;
try {
File file = new File(path);
FileInputStream fis = new FileInputStream(file);
socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
socket.connect();
socket.getOutputStream().write(("img " + file.length()).getBytes());
Thread.sleep(20);
int len = 0;
int count=0;
byte[] b = new byte[1024];
while ((len = fis.read(b)) != -1) {
pb1.setMax(fis.available());
count+=len;
pb1.setProgress(count);
socket.getOutputStream().write(b, 0, len);
}
Log.e("##S", file.getName());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
服务端线程代码
package com.example.as3_day10_liao;
import android.app.Activity;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class ServiceThread extends Thread {
BluetoothSocket socket;
Handler handler;
Activity activity;
public ServiceThread(BluetoothSocket socket, Handler handler, Activity activity) {
this.socket = socket;
this.handler = handler;
this.activity = activity;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
byte[] b=new byte[1024];
int len=is.read(b);
String s = new String(b, 0, len);
String[] split = s.split(" ");
String type = split[0];
int length = Integer.parseInt(split[1]);
// String name = split[2];
// if(name!=null) {
//
// }
if("text".equals(type)){
final StringBuilder sb=new StringBuilder();
int count=0;
while ((len=is.read(b))!=-1){
sb.append(new String(b,0,len));
count+=len;
Thread.sleep(100);
Message message = Message.obtain();
message.obj=length;
message.arg1=count;
message.what=1000;
handler.sendMessage(message);
if(count==length){
break;
}
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity, ""+sb.toString(), Toast.LENGTH_SHORT).show();
}
});
}else if(type.equals("img")){
int count=0;
FileOutputStream fos = new FileOutputStream("/sdcard/" + "测试.jpg");
while ((len=is.read(b))!=-1){
fos.write(b,0,len);
count+=len;
Thread.sleep(100);
Message message = Message.obtain();
message.obj=length;
message.arg1=count;
message.what=1000;
handler.sendMessage(message);
if(count==length){
break;
}
}
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(activity, "收到图片", Toast.LENGTH_SHORT).show();
}
});
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}