Android流媒体研究之一台手机录制,另一台手机播放

最近无聊,做一下android音视频方面的学习和研究。网上有很多案例值得我们去学习。我个人先去大概了解了一下音视频的一些基本概念,然后做了一个小demo,实现了一台手机录制,另一台手机实时播放。视屏录制采用的Camera,预览用的SurfaceView,把采集的视频压缩成bitmap,通过socket进行传输到另外一台手机上。这个demo只是用来学习android Camera,bitmap传输比较耗流量,所以该demo仅供学习。

视频采集客户端:
录制页面activity

package com.fm.camero;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;

import com.fangming.myframwork.R;
import com.fm.qxtapp.MyApp;

import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;

/**
 * @describe 视频录制成图片压缩socket传输
 * @author fangming
 * @CreateTime 2016年8月16日下午2:32:41
 */
public class TestcamoraActivety2 extends ServiceActivity implements Callback, PreviewCallback {

    private TestcamoraActivety2 _this;
    private String TAG = TestcamoraActivety2.class.getSimpleName();
    private Button btn_start;
    private SurfaceView sf_surfaceView;
    private SurfaceHolder suHolder;
    private int width;// 分辨率宽度
    private int height;// 分辨率高度
    private Camera mCamera;
    private boolean isStreaming = false;
    private MyApp myApp;
    private Button btn_puse;
    private ImageView iv_show;
    private Boolean isShow = true;
    int mwidth, mheight;
    private Button btn_switch;
    private Button btn_conn;
    private Button btn_disconn;
    private EditText et_ip;
    private EditText et_port;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_testcamora);
        _this = this;
        initView();
        myApp = MyApp.getInstance();
    }

    private void initSurfaceholder() {
        suHolder = sf_surfaceView.getHolder();
        suHolder.addCallback(this);
        // width = 352;
        // height = 288;
        width = 320;
        height = 480;
        mwidth = width;
        mheight = height;
        System.out.println("*****相机初始化完成*****");
    }

    private void initView() {
        btn_start = (Button) findViewById(R.id.btn_start);
        btn_puse = (Button) findViewById(R.id.btn_puse);
        iv_show = (ImageView) findViewById(R.id.iv_show);
        sf_surfaceView = (SurfaceView) findViewById(R.id.sf_surfaceView);
        initSurfaceholder();
        btn_start.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mCamera.startPreview();
                // new DumpFrameTask().execute();
            }
        });
        btn_puse.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mCamera.stopPreview();
            }
        });
        btn_switch = (Button) findViewById(R.id.btn_switch);
        btn_switch.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

            }
        });

        btn_conn = (Button) findViewById(R.id.btn_conn);
        btn_disconn = (Button) findViewById(R.id.btn_disconn);
        et_ip = (EditText) findViewById(R.id.et_ip);
        et_port = (EditText) findViewById(R.id.et_port);
        btn_conn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                ip = et_ip.getText().toString();
                port = et_port.getText().toString();
                bindMyService();
            }
        });
        btn_disconn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                unBindMyService();
            }
        });

    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        isStreaming = true;
        System.out.println("*****相机采集到的数组长度" + data.length + "*****");
        if (isShow) {
            mwidth = camera.getParameters().getPreviewSize().width;
            mheight = camera.getParameters().getPreviewSize().height;
            isShow = false;
        }
        YuvImage image = new YuvImage(data, ImageFormat.NV21, mwidth, height, null);
        if (image != null) {
            ByteArrayOutputStream outstream = new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, mwidth, height), 80, outstream);

            byte[] arr=outstream.toByteArray();
//          Bitmap bitmap =BitmapFactory.decodeByteArray(arr,0, arr.length);
//          iv_show.setRotation(90);
//          iv_show.setImageBitmap(bitmap);

            mService.sendDate(arr);
            try {
                outstream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open();
        try {
            mCamera.setPreviewDisplay(suHolder);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        mCamera.setPreviewCallback(this);
        List<Size> previewSizes = mCamera.getParameters().getSupportedPreviewSizes();
        width = previewSizes.get(0).width;
        height = previewSizes.get(0).height;
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(width, height);
        // 横竖屏镜头自动调整
        if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
            parameters.set("orientation", "portrait"); //
            parameters.set("rotation", 90); // 镜头角度转90度(默认摄像头是横拍)
            mCamera.setDisplayOrientation(90); // 在2.2以上可以使用
        } else// 如果是横屏
        {
            parameters.set("orientation", "landscape"); //
            mCamera.setDisplayOrientation(0); // 在2.2以上可以使用
        }
        System.out.println("*****surfaceCreated*****");
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        System.out.println("*****系统执行surfaceChanged*****");
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        System.out.println("*****surfaceDestroyed*****");
        if (mCamera != null) {
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

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

    @Override
    public void finish() {
        super.finish();
        Intent mintent = new Intent();
        mintent.setAction(ConnectionService.ACTION);
        stopService(mintent);
    }
}

该activity布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <SurfaceView
        android:id="@+id/sf_surfaceView"
        android:layout_width="match_parent"
        android:layout_height="300dp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="start" />

        <Button
            android:id="@+id/btn_puse"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="暂停" />

        <Button
            android:id="@+id/btn_switch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="转码" />

        <Button
            android:id="@+id/btn_conn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="connect" />

        <Button
            android:id="@+id/btn_disconn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="disconnect" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <EditText
            android:id="@+id/et_ip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="192.168.1.108" />

        <EditText
            android:id="@+id/et_port"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="6001" />
    </LinearLayout>

    <ImageView
        android:id="@+id/iv_show"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:src="@drawable/ic_launcher" />

</LinearLayout>

在这个录制中,遇到的几个比较坑的地方,第一个是视频的宽和高,没有设置好,播放时会导致黑屏或者花屏。还有就是对于camera采集的视频格式的一些问题。默认是ImageFormat.NV21,也就是YUV420sp。

// yuv420P(YV12)或者yuv420SP(NV21/NV12)
parameters.setPreviewFormat(ImageFormat.NV21);

我们采集的视频最后通过onPreviewFrame这个回调接口获得

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        isStreaming = true;
        System.out.println("*****相机采集到的数组长度" + data.length + "*****");
        if (isShow) {
            mwidth = camera.getParameters().getPreviewSize().width;
            mheight = camera.getParameters().getPreviewSize().height;
            isShow = false;
        }
        YuvImage image = new YuvImage(data, ImageFormat.NV21, mwidth, height, null);
        if (image != null) {
            ByteArrayOutputStream outstream = new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, mwidth, height), 80, outstream);

            byte[] arr=outstream.toByteArray();
//          Bitmap bitmap =BitmapFactory.decodeByteArray(arr,0, arr.length);
//          iv_show.setRotation(90);
//          iv_show.setImageBitmap(bitmap);
            //视频发送
            mService.sendDate(arr);
            try {
                outstream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

采集到的视频通过mService.sendDate(arr);进行发送。mService是我自己定义的一个service用来后台处理数据。

ConnectionService类

package com.fm.camero;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;

import com.fm.constants.Constants;
import com.fm.utill.ByteConvertUtils;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class ConnectionService extends Service {
    public final static String ACTION = "com.connectionService";
    private final static int PACKATHEADER_SIGN_LENGTH = 2;// 我的包标识
    private final static int PACKATHEADER_TYPE_LENGTH = 4;// 包类型 4byte
    private final static int PACKATHEADER_DATALEN_LENGTH = 4;// 包长度 4byte
    private final static int PACKATHEADER_LENGTH = PACKATHEADER_SIGN_LENGTH + PACKATHEADER_TYPE_LENGTH
            + PACKATHEADER_DATALEN_LENGTH;// 包头
    private String ipAdd = "192.168.1.109";
    private int port = 6001;
    private String TAG = "ConnectionService";
    private Socket mSocket;
    private OutputStream outStream;
    private InputStream inStream;
    private InitSocketThread initSocketThread;
    private Boolean isAccepte = true;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "---->" + "onCreateservice");
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "---->service停止");
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "---->" + "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 初始化socket线程
     */
    class InitSocketThread extends Thread {

        @Override
        public void run() {
            super.run();
            initSocket();
        }
    }

    /**
     * 初始化socket
     */
    private synchronized void initSocket() {
        Log.e(TAG, "---->创建socket成功");
        try {
            mSocket = new Socket(ipAdd, port);
            if (mSocket.isConnected()) {
                Log.e(TAG, "---->连接成功");
                outStream = mSocket.getOutputStream();
                inStream = mSocket.getInputStream();
            }
        } catch (SocketException e) {
            Log.d(TAG, "socket conn fail");
            e.printStackTrace();
        } catch (IOException e) {
            Log.d(TAG, "socket conn fail");
            e.printStackTrace();
        }
    }

    public class MyBinder extends Binder {

        public ConnectionService getService() {
            return ConnectionService.this;
        }
    }

    public MyBinder mBinder = new MyBinder();

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

    public void sendDate(byte[] data) {
        int datalength = data.length;
        byte[] buffer = new byte[PACKATHEADER_LENGTH + datalength];
        // 设置包头3000
        System.arraycopy(Constants.APPREQUEST_HEAD, 0, buffer, 0, 2);
        // 设置type
        byte[] type = { 0, 0, 0x26, (byte) 0x48 };
        System.arraycopy(type, 0, buffer, 2, 4);
        // 设置长度
        byte[] len = ByteConvertUtils.intToBytes(datalength);
        System.arraycopy(len, 0, buffer, 6, 4);
        // 设置内容
        System.arraycopy(data, 0, buffer, 10, datalength);
        new sendDataThread(buffer).start();
    }

    public class sendDataThread extends Thread {
        byte byteBuffer[] = null;

        public sendDataThread(byte[] data) {
            this.byteBuffer = data;
        }

        public void run() {
            try {
                outStream.write(byteBuffer, 0, byteBuffer.length);
                System.out.println("发送的数据长度:" + byteBuffer.length);
                outStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void setIpAndPort(String ip, String port) {
        if (ip != null && !ip.equals("")) {
            ipAdd = ip;
        }
        if (port != null && !port.equals("")) {
            this.port = Integer.valueOf(port);
        }
        if (initSocketThread == null) {
            initSocketThread = new InitSocketThread();
            initSocketThread.start();
        }
    }

}

以上就是客户端录制,下面是播放客户端

播放端activity

package com.fm.server;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

    private MainActivity _this;
    private ImageView iv_btmap;
    private EditText et_port;
    private Button btn_bind;
    private Button btn_unbind;
    public String mPort;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        _this = this;
        initView();
    }

    private void initView() {
        iv_btmap = (ImageView) findViewById(R.id.iv_btmap);
        et_port = (EditText) findViewById(R.id.et_port);
        btn_bind = (Button) findViewById(R.id.btn_bind);
        btn_unbind = (Button) findViewById(R.id.btn_unbind);
        btn_bind.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                String port = et_port.getText().toString();
                if (port == null || port.equals("")) {
                    Toast.makeText(_this, "端口为null", Toast.LENGTH_SHORT).show();
                    return;
                }
                mPort = port;
                bindService();
            }
        });
        btn_unbind.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                unBindService();
            }
        });
    }

    Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case 0:
                byte[] data = (byte[]) msg.obj;
                if (data == null) {
                    return;
                }
                System.out.println("handle收到的数据:" + data.length);
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 2;
                // Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
                // data.length, options);
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                if (bitmap != null) {
                    iv_btmap.setRotation(90);
                    iv_btmap.setImageBitmap(bitmap);
                }
                break;

            default:
                break;
            }
        };
    };

    @Override
    public void finish() {
        super.finish();
        if (mService != null) {
            unBindService();
        }
    }

    public void bindService() {
        Intent mintent = new Intent();
        mintent.setClass(_this, BindService.class);
        bindService(mintent, conn, Context.BIND_AUTO_CREATE);
    }

    public void unBindService() {
        if (mService != null) {
            unbindService(conn);
        }
    }

    public BindService mService = null;

    ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = ((BindService.MyBinder) service).getService();
            mService.startConn(mPort);
            mService.setHandler(mHandler);
        }
    };

}

播放端service


package com.fm.server;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Arrays;

import com.fm.constants.Constants;
import com.fm.utill.ByteConvertUtils;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class BindService extends Service {
    private String TAG = "BindService";
    public int port = 6001;
    public OutputStream outStream;
    public InputStream inStream;
    public Socket mSocket;
    private InitSocketThread initSocketThread;
    private ReadThread readThread;
    private Boolean isAccepte = true;
    ServerSocket server;
    private final static int PACKATHEADER_SIGN_LENGTH = 2;// 我的包标识
    private final static int PACKATHEADER_TYPE_LENGTH = 4;// 包类型 4byte
    private final static int PACKATHEADER_DATALEN_LENGTH = 4;// 包长度 4byte
    private final static int PACKATHEADER_LENGTH = PACKATHEADER_SIGN_LENGTH + PACKATHEADER_TYPE_LENGTH
            + PACKATHEADER_DATALEN_LENGTH;// 包头

    public void setPort(int port) {
        this.port = port;
    }

    private Handler hander;

    public void setHandler(Handler hander) {
        this.hander = hander;
    }

    public void startConn(String port) {
        if (port != null && !port.equals("")) {
            this.port = Integer.valueOf(port);
        }
        initSocketThread = new InitSocketThread();
        initSocketThread.start();
    }

    /**
     * 初始化socket线程
     */
    class InitSocketThread extends Thread {

        @Override
        public void run() {
            super.run();
            initSocket();
        }
    }

    /**
     * 初始化socket
     */
    private void initSocket() {
        Log.e(TAG, "---->创建socket成功");
        try {
            server = new ServerSocket(port);
            mSocket = server.accept();
            if (mSocket.isConnected()) {
                Log.e(TAG, "---->连接成功");
                outStream = mSocket.getOutputStream();
                inStream = mSocket.getInputStream();
                readThread = new ReadThread();
                readThread.start();
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class ReadThread extends Thread {
        @Override
        public void run() {
            super.run();
            while (isAccepte) {
                if (mSocket != null && mSocket.isConnected()) {
                    devide(new DataInputStream(new BufferedInputStream(inStream)));
                }
            }
        }
    }

    public synchronized void devide(DataInputStream ds) {
        try {
            if (ds.available() > 0) {
                recv(ds);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void recv(DataInputStream dis) throws IOException {
        byte[] head = new byte[PACKATHEADER_LENGTH];
        Log.e(TAG, "---->>接收数据的长度" + dis.available());
        try {
            dis.readFully(head, 0, PACKATHEADER_LENGTH);
        } catch (IOException e) {
            return;
        }
        // 读取前两个字节我的数据包标识head[]
        byte[] sign = new byte[2];
        sign = Arrays.copyOfRange(head, 0, 2);
        if (ByteConvertUtils.bytesToInt2(sign) != Constants.APP_CTL_HEAD) {
            return;
        }
        // 读取4byte包类型
        byte[] type = new byte[4];
        type = Arrays.copyOfRange(head, 2, 6);
        int nType = ByteConvertUtils.bytesToInt(type);

        // 读取4byte内容长度
        byte[] datalen = new byte[4];
        datalen = Arrays.copyOfRange(head, 6, 10);
        int nDatalen = ByteConvertUtils.bytesToInt(datalen);
        Log.e(TAG, "type:" + nType);

        switch (nType) {// App登陆/查询网关
        case Constants.VEDIO_STREAM:
            byte[] data = null;
            if (nDatalen > 0) {
                // 接收指定长度的内容
                data = new byte[nDatalen];
                dis.readFully(data, 0, nDatalen);
                Log.e(TAG, "len:" + nDatalen);
                sendMessage(data);
            }
            break;
        default:
            Log.e(TAG, "---->不识别的命令");
            break;
        }
    };

    public void sendMessage(byte[] data) {
        Message msg = hander.obtainMessage();
        msg.what = 0;
        msg.obj = data;
        hander.sendMessage(msg);
    }

    @Override
    public void onCreate() {
        Log.e(TAG, "---->" + "onCreateservice");
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "---->service停止");
        super.onDestroy();
        isAccepte = false;
        if (readThread != null && readThread.isAlive()) {
            readThread.interrupt();
            readThread = null;
        }
        initSocketThread.interrupt();
        initSocketThread = null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "---->" + "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    public class MyBinder extends Binder {

        public BindService getService() {
            return BindService.this;
        }
    }

    public MyBinder mBinder = new MyBinder();

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

主要用来和视频采集端进行socket通信。

另外附上一个简单的静态类

package com.fm.constants;

public class Constants {
    public static final int APP_CTL_HEAD = 3000;// 包头标识
    public static final byte[] APPREQUEST_HEAD={0x0b,(byte) 0xB8};//包头标识

    public static final int VEDIO_STREAM = 9800;//服务端将要发送播放视频命令
}

工具类:

package com.fangming.utill;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import android.util.Log;

public class ByteConvertUtils {  

    /** 
     * 长整形转byte数组 
     *  
     * @param n 
     *            长整形数字 
     * @return 转换后的数组 
     */  
    public static byte[] longToBytes(long n) {  
        byte[] b = new byte[8];  
        b[7] = (byte) (n & 0xff);  
        b[6] = (byte) (n >> 8 & 0xff);  
        b[5] = (byte) (n >> 16 & 0xff);  
        b[4] = (byte) (n >> 24 & 0xff);  
        b[3] = (byte) (n >> 32 & 0xff);  
        b[2] = (byte) (n >> 40 & 0xff);  
        b[1] = (byte) (n >> 48 & 0xff);  
        b[0] = (byte) (n >> 56 & 0xff);  
        return b;  
    }  

    public static short[] ByteToShortArray(byte[] byteArray)
    {
        short[] shortArray = new short[byteArray.length/2];
        ByteBuffer.wrap(byteArray).order(ByteOrder.BIG_ENDIAN).asShortBuffer().get(shortArray);
        return shortArray;
    }

    public static byte[] StringToByteArray(String houseNo)
    {

        Log.i("houseNo.length","houseNo.length"+houseNo.length());
        byte[] byteArray=new byte[houseNo.length()];
        for(int i=0;i<houseNo.length();i++)
        {
            byteArray[i]=Byte.parseByte(""+houseNo.charAt(i));
        }
        return byteArray;
    }

    /** 
     * 长整形转byte数组 
     *  
     * @param n 
     *            长整形数字 
     * @param array 
     *            转换后的结果 
     * @param offset 
     *            从第offset位开始转换 
     */  
    public static void longToBytes(long n, byte[] array, int offset) {  
        array[7 + offset] = (byte) (n & 0xff);  
        array[6 + offset] = (byte) (n >> 8 & 0xff);  
        array[5 + offset] = (byte) (n >> 16 & 0xff);  
        array[4 + offset] = (byte) (n >> 24 & 0xff);  
        array[3 + offset] = (byte) (n >> 32 & 0xff);  
        array[2 + offset] = (byte) (n >> 40 & 0xff);  
        array[1 + offset] = (byte) (n >> 48 & 0xff);  
        array[0 + offset] = (byte) (n >> 56 & 0xff);  
    }  

    /**
     * 将指定byte数组以16进制的形式打印到控制台
     * @param hint String
     * @param b byte[]
     * @return void
     */
    public static String printHexString( byte[] b) {
        StringBuffer returnValue = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            System.out.print(hex.toUpperCase() + " ");
            returnValue.append(hex.toUpperCase() + " ");
        }

        return "[" + returnValue.toString() + "]";
    }

    /**
     *
     * @param b byte[]
     * @return String
     */
    public static String Bytes2HexString(byte[] b) {
        String ret = "";
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret += hex.toUpperCase();
        }
        return ret;
    }

    /*
     * 字节数组转换成Int数    读取后四个字节的内容长度
     */
    public static int byte2Int(byte[] b) {
        int intValue = 0;
        for (int i = 0; i < b.length; i++) {
            intValue += (b[i] & 0xFF) << (8 * (i));
        }
        return intValue;
    }

    /** 
     * bytes 转 Long 
     *  
     * @param array 
     *            要转换的byte 
     * @return long长整形数字 
     */  
    public static long bytesToLong(byte[] array) {  
        return ((((long) array[0] & 0xff) << 56) | (((long) array[1] & 0xff) << 48) | (((long) array[2] & 0xff) << 40)  
                | (((long) array[3] & 0xff) << 32) | (((long) array[4] & 0xff) << 24)  
                | (((long) array[5] & 0xff) << 16) | (((long) array[6] & 0xff) << 8) | (((long) array[7] & 0xff) << 0));  
    }  

    public static short[] bytesToShorts(byte byteBuffer[]) {
        int len = byteBuffer.length/2;
        short[] output = new short[len];
        int j = 0;

        for (int i = 0; i < len; i++) {
            output[i] = (short) (byteBuffer[j++] << 8);
            output[i] |= (byteBuffer[j++] & 0xff);

//            output[i] = (short) (byteBuffer[j++] << 8);
//            output[i] += ((0x7f &byteBuffer[j]) + (byteBuffer[j] < 0 ? 128 : 0));
//            j++;

        }
        return output;
    }


    public static byte[] shortsToBytes(short shortBuffer[]) {
        int len = shortBuffer.length;
        byte[] output = new byte[len*2];
        int j = 0;

        for (int i = 0; i < len; i++) {
            output[j++] = (byte) (shortBuffer[i] >>> 8);
            output[j++] = (byte) (0xff & shortBuffer[i]);
        }
        return output;
    }

    /**
     * 将指定字符串src,以每两个字符分割转换为16进制形式 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF,
     * 0xD9}
     * 
     * @param src
     *            String
     * @return byte[]
     */
    public static byte[] hexString2Bytes(String src) {
        if (src == null || "".equals(src)) {
            return null;
        }
        byte[] tmp = src.getBytes();
        int len = tmp.length / 2;
        if (len <= 0) {
            return null;
        }
        byte[] ret = new byte[len];

        for (int i = 0; i < len; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }

    /**
     * 将两个ASCII字符合成一个字节; 如:"EF"--> 0xEF
     * 
     * @param src0
     *            byte
     * @param src1
     *            byte
     * @return byte
     */
    public static byte uniteBytes(byte src0, byte src1) {
        byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))
                .byteValue();
        _b0 = (byte) (_b0 << 4);
        byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))
                .byteValue();
        byte ret = (byte) (_b0 ^ _b1);
        return ret;
    }

    /** 
     * byte数组转长整形数字 
     *  
     * @param array 
     *            要转换的byte数组 
     * @param offset 
     *            从第offset开始转换 
     * @return 转换后的长整形数字 
     */  
    public static long bytesToLong(byte[] array, int offset) {  
        return ((((long) array[offset + 0] & 0xff) << 56) | (((long) array[offset + 1] & 0xff) << 48)  
                | (((long) array[offset + 2] & 0xff) << 40) | (((long) array[offset + 3] & 0xff) << 32)  
                | (((long) array[offset + 4] & 0xff) << 24) | (((long) array[offset + 5] & 0xff) << 16)  
                | (((long) array[offset + 6] & 0xff) << 8) | (((long) array[offset + 7] & 0xff) << 0));  
    }  

    public static byte[] intToBytes(int n) {  
        byte[] b = new byte[4];  
        b[3] = (byte) (n & 0xff);  
        b[2] = (byte) (n >> 8 & 0xff);  
        b[1] = (byte) (n >> 16 & 0xff);  
        b[0] = (byte) (n >> 24 & 0xff);  
        return b;  
    }  

    public static void intToBytes(int n, byte[] array, int offset) {  
        array[3 + offset] = (byte) (n & 0xff);  
        array[2 + offset] = (byte) (n >> 8 & 0xff);  
        array[1 + offset] = (byte) (n >> 16 & 0xff);  
        array[offset] = (byte) (n >> 24 & 0xff);  
    }  

    /** 
     * @param b 
     * @return 
     */  
    public static int bytesToInt(byte b[]) {  
        return b[3] & 0xff | (b[2] & 0xff) << 8 | (b[1] & 0xff) << 16 | (b[0] & 0xff) << 24;  
    } 

    /** 
     * @param b 
     * @return 
     */  
    public static int bytesToInt2(byte b[]) {  
        return b[1] & 0xff | (b[0] & 0xff) << 8;  
    }  

    /** 
     * byte 数组转 int 
     *  
     * @param b 
     *            byte数组 
     * @param offset 
     *            从数组的第几位开始转 
     * @return 整形 
     */  
    public static int bytesToInt(byte b[], int offset) {  
        return b[offset + 3] & 0xff | (b[offset + 2] & 0xff) << 8 | (b[offset + 1] & 0xff) << 16  
                | (b[offset] & 0xff) << 24;  
    }  

    /** 
     * 无符号整形转数组 
     *  
     * @param n 
     *            要转换的整形 
     * @return byte数组 
     */  
    public static byte[] uintToBytes(long n) {  
        byte[] b = new byte[4];  
        b[3] = (byte) (n & 0xff);  
        b[2] = (byte) (n >> 8 & 0xff);  
        b[1] = (byte) (n >> 16 & 0xff);  
        b[0] = (byte) (n >> 24 & 0xff);  

        return b;  
    }  

    public static void uintToBytes(long n, byte[] array, int offset) {  
        array[3 + offset] = (byte) (n);  
        array[2 + offset] = (byte) (n >> 8 & 0xff);  
        array[1 + offset] = (byte) (n >> 16 & 0xff);  
        array[offset] = (byte) (n >> 24 & 0xff);  
    }  

    public static long bytesToUint(byte[] array) {  
        return ((long) (array[3] & 0xff)) | ((long) (array[2] & 0xff)) << 8 | ((long) (array[1] & 0xff)) << 16  
                | ((long) (array[0] & 0xff)) << 24;  
    }  

    public static long bytesToUint(byte[] array, int offset) {  
        return ((long) (array[offset + 3] & 0xff)) | ((long) (array[offset + 2] & 0xff)) << 8  
                | ((long) (array[offset + 1] & 0xff)) << 16 | ((long) (array[offset] & 0xff)) << 24;  
    }  

    public static byte[] shortToBytes(short n) {  
        byte[] b = new byte[2];  
        b[1] = (byte) (n & 0xff);  
        b[0] = (byte) ((n >> 8) & 0xff);  
        return b;  
    }  

    public static void shortToBytes(short n, byte[] array, int offset) {  
        array[offset + 1] = (byte) (n & 0xff);  
        array[offset] = (byte) ((n >> 8) & 0xff);  
    }  

    public static short bytesToShort(byte[] b) {  
        return (short) (b[1] & 0xff | (b[0] & 0xff) << 8);  
    }  

    public static short bytesToShort(byte[] b, int offset) {  
        return (short) (b[offset + 1] & 0xff | (b[offset] & 0xff) << 8);  
    }  

    public static byte[] ushortToBytes(int n) {  
        byte[] b = new byte[2];  
        b[1] = (byte) (n & 0xff);  
        b[0] = (byte) ((n >> 8) & 0xff);  
        return b;  
    }  

    public static void ushortToBytes(int n, byte[] array, int offset) {  
        array[offset + 1] = (byte) (n & 0xff);  
        array[offset] = (byte) ((n >> 8) & 0xff);  
    }  

    public static int bytesToUshort(byte b[]) {  
        return b[1] & 0xff | (b[0] & 0xff) << 8;  
    }  

    public static int bytesToUshort(byte b[], int offset) {  
        return b[offset + 1] & 0xff | (b[offset] & 0xff) << 8;  
    }  

    public static byte[] ubyteToBytes(int n) {  
        byte[] b = new byte[1];  
        b[0] = (byte) (n & 0xff);  
        return b;  
    }  

    public static void ubyteToBytes(int n, byte[] array, int offset) {  
        array[0] = (byte) (n & 0xff);  
    }  

    public static int bytesToUbyte(byte[] array) {  
        return array[0] & 0xff;  
    }  

    public static int bytesToUbyte(byte[] array, int offset) {  
        return array[offset] & 0xff;  
    }  
    // char 类型、 float、double 类型和 byte[] 数组之间的转换关系还需继续研究实现。  


}

就写到这里,欢迎加我的qq和我交流,也可以加入我们的开发交流群。
个人qq:2385313404
开发交流qq群:574424529

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值