您的位置 首页 java

蓝牙热敏打印机安卓源代码分析

最近在研究android的蓝牙打印机程序,中间遇到不少坑,在这里分享一下我的经历。

先来看打印过程:

1、申请必要的权限

2、确定本机有蓝牙硬件,并且打开蓝牙适配器

3、开通广播接收功能,用于发现蓝牙设备回传的周围蓝牙设备

4、发送蓝牙发现信号广播,周边设备收到这个信号后,会回传自己的mac地址和设备名

5、通过广播收到周边蓝牙设备mac,通过mac地址,连接到指定的蓝牙打印机,获取socket。

6、通过socket发送GB2312编码的字符串,打印完成。

热敏打印机一般都自带字库,所以直接发送文字给打印机就可以打印出想要的东西,如果要打印其它字体、图片、二维码和条形码,只能通过ESC指令,把这些换算成坐标,通过写点的方式打印。

ESC打印控制指令,可以对文字大小、对齐进行各种控制,大家可以网上搜索具体指令。

部分源代码来源于网上整理。

请使用手机真机测试,并且打开需要的各种权限,特别是打开手机上的位置获取权限,因为这个我在手机上没有打开,一直没有收到设备广播数据,折腾了很久。

下面看源代码

AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="#34;
    xmlns:tools="#34;
    package="com.example.myapp2">

    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />

    <!-- 蓝牙-->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
    <!-- 仅在支持BLE(即蓝牙4.0)的设备上运行-->
    <uses-permission android:name="android.hardware.bluetooth_le" android:required="true"/>
    <!-- 如果Android 6.0蓝牙搜索不到设备,需要补充下面两个权限-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>



    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Myapp2">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>  

MainActivity.java

注意那个UUID,不可以随便修改,不然无法连接上打印机,我这里省略了显示蓝牙设备列表的程序,找到打印就直接使用了。

 package com.example.myapp2;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {

    private Button btn_bt_open;
    private Button btn_bt_start;

    private TextView txtinfo;

    private BluetoothAdapter mBluetooth;
    private int mOpenCode = 0x01;


    private BluetoothDevice deviceprint;

  //通过广播,接收周边蓝牙设备信息
    private BroadcastReceiver discoveryReceiver = new BroadcastReceiver() {
        @SuppressLint("MissingPermission")
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Log.i("myapp", "action:" + action);
            //获得已经搜索到的蓝牙设备
            if (action.equals(BluetoothDevice.ACTION_FOUND)) {//发现新的蓝牙设备
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Log.i("myapp", "Find:" + device.getAddress());
                Log.i("myapp", "Find:" + device.getName());
                if (device.getAddress().equals("99:32:88:A6:19:FE")) {
                    //找到打印机直接使用
                    deviceprint = mBluetooth.getRemoteDevice("99:32:88:A6:19:FE");
                    mBluetooth.cancelDiscovery();
                }
            }
        }
    };


    @Override
    protected void onStart() {
        super.onStart();
        //需要过滤多个动作,则调用IntentFilter对象的addAction添加新动作
        IntentFilter discoveryFilter = new IntentFilter();
        Log.i("myapp", "Reg discoverReceiver");
        discoveryFilter.addAction(BluetoothDevice.ACTION_FOUND);
        //注册蓝牙设备搜索的广播接收器
        Intent intent = registerReceiver(discoveryReceiver, discoveryFilter);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //注销蓝牙设备搜索的广播接收器
        unregisterReceiver(discoveryReceiver);
    }


    @SuppressLint("MissingPermission")
    private void beginDiscovery() {
        //如果当前不是正在搜索,则开始新的搜索任务
        if (mBluetooth.isDiscovering() != true) {
            Log.i("myapp", "Start find BlueTooth");
            mBluetooth.startDiscovery();//开始扫描周围的蓝牙设备
        }
    }

    @SuppressLint("MissingPermission")
    private void startBluetooth() {
        //弹出是否允许扫描蓝牙设备的选择对话框
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        startActivityForResult(intent, mOpenCode);
    }

    BluetoothSocket socket;

    @SuppressLint("MissingPermission")
    private void printtxt() {
        if (deviceprint == null) return;
        if (mBluetooth.isDiscovering()) mBluetooth.cancelDiscovery();//关闭扫描
        UUID uuid= UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//不可以修改,这个值对应打印机
        try {
            socket = deviceprint.createRfcommSocketToServiceRecord(uuid);
        } catch (IOException e) {
            e.printStackTrace();
        }

        new Thread() { //蓝牙连接必须新开一个线程
            @Override
            public void run() {
                if (socket == null) return;
                try {
                    if (socket.isConnected() == false)socket.connect();
                    String otxt = "OKrn打印汉字测试rnHeHern";
                    OutputStream outs = socket.getOutputStream();
                    //InputStream ins=socket.getInputStream();

                    outs.write(0x1B);
                    outs.write(0x40);
                    outs.flush(); //ESC初始化打印机

                    outs.write(0x1B);
                    outs.write(0x61);
                    outs.write(0x0); //0居左  1居中 2 居右
                    outs.flush(); //ESC初始化打印机

                    outs.write(otxt.getBytes("gb2312")); //这里必须与打印机内部编码一样,不然打印汉字是乱码
                    outs.flush();
                    //Log.i("myapp","input:"+String.copyValueOf(ins.read())
                    outs.close();
                    Log.i("myapp", "print finish");
                    //socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }


        }.start();


    }

    /**
     * 初始化蓝牙适配器
     */    private void initBluetooth() {

        //Android从4.3开始增加支持BLE技术(即蓝牙4.0以上版本)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            //从系统服务中获取蓝牙管理器
            BluetoothManager bm = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            mBluetooth = bm.getAdapter();
            Log.i("myapp", "从系统服务中获取蓝牙管理器");
        } else {
            //获取系统默认的蓝牙适配器
            mBluetooth = BluetoothAdapter.getDefaultAdapter();
            Log.i("myapp", "获取系统默认的蓝牙适配器");
        }

        if (mBluetooth == null) {
            txtinfo.setText("本机没有蓝牙");
            Log.i("findresult", "没有找到蓝牙");
        } else {
            txtinfo.setText("本机有蓝牙设备");
            Log.i("findresult", "本机有蓝牙");
            startBluetooth();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_bt_open = (Button) findViewById(R.id.btn_bt_open);
        btn_bt_start = (Button) findViewById(R.id.btn_bt_print);
        txtinfo = (TextView) findViewById(R.id.textinfo);

        btn_bt_open.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                initBluetooth();
            }
        });

        btn_bt_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                printtxt();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == mOpenCode) {//来自允许蓝牙扫描的对话框
            if (resultCode == 120) {
                txtinfo.setText("允许本地蓝牙被附近的其他蓝牙设备发现");
                //延迟50毫秒后启动蓝牙设备的刷新任务
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        Log.i("myApp", "开始查找蓝牙...");
                        beginDiscovery();
                    }
                }, 50);
            } else {
                txtinfo.setText("不允许蓝牙被附近的其他蓝牙设备发现");
            }
        }
    }

}  

activity_main.xml

 <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="#34;
    xmlns:app="#34;
    xmlns:tools="#34;
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        tools:layout_editor_absoluteX="1dp"
        tools:layout_editor_absoluteY="1dp">

        <Button
            android:id="@+id/btn_bt_open"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="获取蓝牙" />

        <Button
            android:id="@+id/btn_bt_print"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="蓝牙打印" />

        <TextView
            android:id="@+id/textinfo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="TextView" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>  

文章来源:智云一二三科技

文章标题:蓝牙热敏打印机安卓源代码分析

文章地址:https://www.zhihuclub.com/181491.shtml

关于作者: 智云科技

热门文章

网站地图