蓝牙链接:
Android做蓝牙开发最大的也是唯一的一个坑就是你要分清楚传统蓝牙和低功耗蓝牙(Bluetooth Low Energy),他们的API不一样,也不通用。
区别他们也很容易:低功耗蓝牙顾名思义,用于功耗低的设备,比如各种智能手环、心率仪。你可以直接查阅官方文档,我认为官方文档是最好的资料,里面有很详细的例子,传统蓝牙有中文翻译,低功耗蓝牙则没有
android中蓝牙的打开、搜索主要分为以下几步。
1.在AndroidManifest.xml中添加蓝牙权限。
<!-- 管理蓝牙设备的权限 -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 在sd卡中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions"/>
<!-- 向SD卡写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CLEAR_APP_CACHE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
2.启动蓝牙
private boolean openBtDevice() {
// 获得蓝牙匹配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 蓝牙设备不被支持
if (mBluetoothAdapter == null) {
Log.e(TAG, "Your device is not support Bluetooth!");
Toast.makeText(this, "该设备没有蓝牙设备", Toast.LENGTH_LONG).show();
return false;
}
// 使能蓝牙设备
if (!mBluetoothAdapter.isEnabled()) {
// 隐式Intent
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUES_BT_ENABLE_CODE);
} else {
Toast.makeText(this, "蓝牙打开成功!", Toast.LENGTH_SHORT).show();
}
return true;
}
// 当startActivityForResult启动的 画面结束的时候,该方法被回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUES_BT_ENABLE_CODE && resultCode == RESULT_OK) {
Toast.makeText(this, "蓝牙打开成功!", Toast.LENGTH_SHORT).show();
}
}
3.搜索蓝牙
已经配对过的蓝牙设备
private void findBtDevice() {
Set pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if (mDeviceList.contains(device)) {
return;
}
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mDeviceList.add(device);
}
}
adapter.notifyDataSetChanged();
}
动态注册广播搜索蓝牙
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
//广播用于动态的添加搜索到的蓝牙到ListView中显示
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
//发现的蓝牙设备
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//发现的蓝牙设备已存在则跳过
if (mDeviceList.contains(device)) {
return;
}
//添加发现的蓝牙设备
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
mDeviceList.add(device);
//更新到ListView
adapter.notifyDataSetChanged();
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
//搜索结束,关闭滚动条
setProgressBarIndeterminateVisibility(false);
}
}
};
//下面是一个简单的蓝牙搜索显示蓝牙示例//
首先新建工程、接着在在AndroidManifest.xml中添加蓝牙权限。
编写布局文件
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
android:id="@+id/XianShi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="无内容" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
android:id="@+id/SendText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:hint="请输入" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="MySend"
android:text="发送" />
android:id="@+id/FindBt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="搜索" />
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="蓝牙列表" />
android:id="@+id/DeviceList"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
/编写源代码//
public class MainActivity extends Activity {
private EditText mET; //发送内容,本示例未用到
private Button MyScan; //搜索按钮
private TextView MyMessage; //显示内容,本示例未用到
private ListView MyBtList; //显示蓝牙列表的ListView
private BluetoothAdapter mBluetoothAdapter; //蓝牙适配器
private ArrayAdapter adapter; //Listview使用的适配器
private ArrayList mArrayAdapter = new ArrayList(); //保存ListView显示蓝牙设备的内容
private ArrayList mDeviceList = new ArrayList(); //保存查找的蓝牙设备,避免在ListView重复显示
private static final String TAG = "MyBluetooth"; //调试用
private static final int REQUES_BT_ENABLE_CODE = 0x1002; // 蓝牙使能请求码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); //请求显示滚动条
setContentView(R.layout.activity_main);
//UI注册
mET = (EditText) findViewById(R.id.SendText);
MyScan = (Button) findViewById(R.id.FindBt);
MyMessage = (TextView) findViewById(R.id.XianShi);
MyBtList = (ListView) findViewById(R.id.DeviceList);
//ListView添加适配器
adapter = new ArrayAdapter(this,
android.R.layout.simple_list_item_1, mArrayAdapter);
MyBtList.setAdapter(adapter);
openBtDevice(); //打开蓝牙
//搜索蓝牙按钮点击事件
MyScan.setOnClickListener(new MyScanClick());
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
// 动态注册广播接收器
// 用来接收扫描到的设备信息
registerReceiver(mReceiver, filter);
}
//搜索蓝牙按钮点击事件
private class MyScanClick implements OnClickListener {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!mBluetoothAdapter.isDiscovering()) {
findBtDevice(); //打开蓝牙
mBluetoothAdapter.startDiscovery(); //开始搜索
setProgressBarIndeterminateVisibility(true); //显示滚动条
}
}
}
//广播用于动态的添加搜索到的蓝牙到ListView中显示
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
//发现的蓝牙设备
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//发现的蓝牙设备已存在则跳过
if (mDeviceList.contains(device)) {
return;
}
//添加发现的蓝牙设备
mArrayAdapter
.add(device.getName() + "\n" + device.getAddress());
mDeviceList.add(device);
//更新到ListView
adapter.notifyDataSetChanged();
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
//搜索结束,关闭滚动条
setProgressBarIndeterminateVisibility(false);
}
}
};
//之前已经配对的蓝牙,添加到ListView
private void findBtDevice() {
Set pairedDevices = mBluetoothAdapter
.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
if (mDeviceList.contains(device)) {
return;
}
mArrayAdapter
.add(device.getName() + "\n" + device.getAddress());
mDeviceList.add(device);
}
}
adapter.notifyDataSetChanged();
}
//打开蓝牙
private boolean openBtDevice() {
// 获得蓝牙匹配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 蓝牙设备不被支持
if (mBluetoothAdapter == null) {
Log.e(TAG, "Your device is not support Bluetooth!");
Toast.makeText(this, "该设备没有蓝牙设备", Toast.LENGTH_LONG).show();
return false;
}
// 使能蓝牙设备
if (!mBluetoothAdapter.isEnabled()) {
// 隐式Intent
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUES_BT_ENABLE_CODE);
} else {
Toast.makeText(this, "蓝牙打开成功!", Toast.LENGTH_SHORT).show();
}
return true;
}
// 当startActivityForResult启动的 画面结束的时候,该方法被回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUES_BT_ENABLE_CODE && resultCode == RESULT_OK) {
Toast.makeText(this, "蓝牙打开成功!", Toast.LENGTH_SHORT).show();
}
}
}
蓝牙打印
链接打印机后,执行以下代码:打印文字,格式类似于外卖单:
public class PrintTextActivityextends Activity {
List>listData =new ArrayList>();
private EditTextet_input;
private CheckBoxcheckBoxAuto;
private Buttonbt_print;
private Threadautoprint_Thread;
int times =500;// Automatic print time interval
boolean isPrint =true;
Stringmessage="";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_print_text);
isPrint =true;
et_input = (EditText) findViewById(R.id.et_input_1);
//et_input.setText("Printing test\n");
bt_print = (Button) findViewById(R.id.bt_print);
bt_print.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
message=et_input.getText().toString().trim();
try {
byte[] send=message.getBytes("GBK");
PrintService.pl.write(send);
}catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
PrintService.pl.printText("\n");
PrintService.pl.write(new byte[]{0x1b,0x61,0x01});
//PrintService.pl.write(new byte[] { 0x1d, 0x0c });
PrintService.pl.write(new byte[] {0x1b,0x21,0x11 });
PrintService.pl.printText("xxx");
//修改文字模式为加粗模式
PrintService.pl.write(new byte[]{0X1b,0x45,0x01});
PrintService.pl.write(new byte[]{0x1d,0x21,0x03});
PrintService.pl.printText("\n");
//修改文字加粗模式为0
PrintService.pl.write(new byte[]{0x1b,0x21,0x00});
//文字居中
PrintService.pl.write(new byte[]{0x1b,0x61,0x01});
PrintService.pl.printText("已支付");
PrintService.pl.printText("\n");
PrintService.pl.printText("下单时间:10—24"+"\t"+"11:15");
PrintService.pl.printText("\n");
PrintService.pl.printText("货号"+"\t"+"\t"+"\t"+"\t"+"\t"+"数量"+"\t"+"价格");
PrintService.pl.printText("-----------------------------");
PrintService.pl.printText("\n");
PrintService.pl.printText("GP-3120TU"+"\t"+"\t"+"\t"+"\t"+"X1"+"\t"+"\t"+"286");
PrintService.pl.printText("\n");
PrintService.pl.printText("GP-1124D"+"\t"+"\t"+"\t"+"\t"+"X2"+"\t"+"\t"+"560");
PrintService.pl.printText("\n");
PrintService.pl.printText("GP-1124T"+"\t"+"\t"+"\t"+"\t"+"X1"+"\t"+"\t"+"698");
PrintService.pl.printText("\n");
PrintService.pl.printText("-----------------------------");
PrintService.pl.printText("\n");
PrintService.pl.printText("实收" +"\t" +"\t" +"\t" +"\t" +"¥" +"\t" +"1603");
PrintService.pl.printText("\n");
PrintService.pl.printText("找零" +"\t" +"\t" +"\t" +"\t" +"¥" +"\t" +"2");
PrintService.pl.printText("\n");
PrintService.pl.printText("-----------------------------");
PrintService.pl.printText("\n");
PrintService.pl.write(new byte[]{0x1b,0x61,0x01});
PrintService.pl.printText("请保管好购物凭证");
PrintService.pl.printText("\n");
PrintService.pl.write(new byte[]{0x1b,0x61,0x01});
PrintService.pl.printText("多谢惠顾");
}
});
checkBoxAuto = (CheckBox) findViewById(R.id.checkBoxAuto);
// Auto Print
autoprint_Thread =new Thread() {
public void run() {
while (isPrint) {
if (checkBoxAuto.isChecked()) {
String message =et_input.getText().toString();
PrintService.pl.printText(message);
PrintService.pl.write(new byte[] {0x1d,0x0c });
try {
Thread.sleep(times);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
autoprint_Thread.start();
// et_input.addTextChangedListener(textWatcher);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
Resources res = getResources();
String[] cmdStr = res.getStringArray(R.array.cmd);
for (int i =0; i < cmdStr.length; i++) {
String[] cmdArray = cmdStr[i].split(",");
if (cmdArray.length ==2) {
Map map =new HashMap();
map.put("title", cmdArray[0]);
map.put("description", cmdArray[1]);
menu.add(0, i, i, cmdArray[0]);
listData.add(map);
}
}
return true;
}
@Override
public boolean onOptionsItemSelected(android.view.MenuItem item) {
Map map =listData.get(item.getItemId());
String cmd = map.get("description").toString();
byte[] bt = PrintCmdActivity.hexStringToBytes(cmd);
PrintService.pl.write(bt);
Toast toast = Toast.makeText(this,"Send Success", Toast.LENGTH_SHORT);
toast.show();
return false;
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
isPrint =false;
super.onStop();
}
private static Bitmap resizeImage(Bitmap bitmap,int w,int h) {
Bitmap BitmapOrg = bitmap;
int width = BitmapOrg.getWidth();
int height = BitmapOrg.getHeight();
if (width > w) {
float scaleWidth = ((float) w) / width;
float scaleHeight = ((float) h) / height +24;
Matrix matrix =new Matrix();
matrix.postScale(scaleWidth, scaleWidth);
Bitmap resizedBitmap = Bitmap.createBitmap(BitmapOrg,0,0, width,
height, matrix,true);
return resizedBitmap;
}else {
Bitmap resizedBitmap = Bitmap.createBitmap(w, height +24,
Config.RGB_565);
Canvas canvas =new Canvas(resizedBitmap);
Paint paint =new Paint();
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(bitmap, (w - width) /2,0, paint);
return resizedBitmap;
}
}
}