본문 바로가기
Android

Bluetooth file & text transfer #2 server

by 캡틴노랑이 2021. 3. 17.
반응형

test device : note 4

android os : Marshmallow 6.0

 

server source

 

Source

activity_bluetooth1.xml

 

Bluetooth1Activity.java

package com.example.sampleproject;


import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.example.sampleproject.Data.BlueToothData;
import com.example.sampleproject.Data.SettingValue;
import com.example.sampleproject.Helper.DataTypeHelper;
import com.example.sampleproject.Norang.NorangActivity;
import com.example.sampleproject.Norang.SettingData;
import com.example.sampleproject.Data.BlueToothData;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.bluetooth.BluetoothServerSocket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.nio.charset.Charset;


public class Bluetooth1Activity extends NorangActivity {    
    private TextView tvLog;

    private BluetoothAdapter bluetoothAdapter;
    private BluetoothServerSocket serverSocket;
    private BluetoothSocket socket;

    private ServerThread serverThread;
    private ListenerThread listenerThread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bluetooth1);

        InitializeControl();
        InitializeCommonDataBind();
    }

    protected void InitializeControl() {
        toolbar = findViewById(R.id.tbToolBar);
        setToolbar("");

        tvLog=findViewById(R.id.tvLog);

        
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_EXTERNAL_STORAGE)) {
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1);
            }
        }

        
        if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
    }

    protected void InitializeCommonDataBind() {
        
        bluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
        if(bluetoothAdapter==null){
            Toast.makeText(this, "This machine doesn't have bluetooth.", Toast.LENGTH_SHORT).show();
            finish();
            return;
        }
        
        if(bluetoothAdapter.isEnabled()){
            //서버소켓 생성 작업 실행
            CreateBluetoothSocket();

        }else{
            
            Intent intent= new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, SettingValue.BT_REQ_ENABLE);
        }
    }

    private Handler listenerHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            BlueToothData data = (BlueToothData)msg.obj;

            switch(data.getMessage_type())
            {
                case TEXT:
                    tvLog.append("new " + new String(data.getData(), 0, data.getData().length));
                    break;
                case FILE:
                    Log.d("listenerHandler", "receive file");

                    try{
                        Log.d("listenerHandler", "Save");
                        File file = new File("/storage/emulated/0/1234/00001.jpg"); //new File(data.getFileName());
                        FileOutputStream fos = new FileOutputStream(file);

                        fos.write(data.getData());
                        fos.close();
                        Log.d("listenerHandler", "End");
                        tvLog.append("wrote the file.");
                    }catch(Throwable e){
                        Log.e("file", "listenerHandler: Error writing to file. " + e.getMessage() );
                    }
                    break;
            }

        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode){
            case SettingValue.BT_REQ_ENABLE:
                if(resultCode == RESULT_CANCELED){                    
                    Toast.makeText(this, "not allow bluetooth.", Toast.LENGTH_SHORT).show();
                    finish();
                }else{                    
                    CreateBluetoothSocket();
                }
                break;
            case SettingValue.BT_REQ_DISCOVERYABLE:
                if(resultCode == RESULT_CANCELED)
                    Toast.makeText(this, "can't find bluetooth.", Toast.LENGTH_SHORT).show();
                break;
        }

    }// onActivityResult
    
    protected void CreateBluetoothSocket(){
        serverThread= new ServerThread();
        serverThread.start();
        
        AllowDiscovery();
    }
    
    protected void AllowDiscovery(){
    
        Intent intent= new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);     
        intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);// 300초
        startActivityForResult(intent, SettingValue.BT_REQ_DISCOVERYABLE);
    }

    public void btnSendTextOnClick(View view)
    {
        listenerThread.write(SettingValue.BT_MESSAGE_TYPE.TEXT, "Server sent test message.\n");
        //listenerThread.write("Server sent test message.\n".getBytes());
    }

    public void btnSendFileOnClick(View view)
    {
        ///storage/self/primary/DCIM/Camera/20190616_233731.jpg //1m
        //listenerThread.write(SettingValue.BT_MESSAGE_TYPE.FILE, "/storage/emulated/0/Download/m_1548925438_9398_i16252312250.gif");
        //listenerThread.write(SettingValue.BT_MESSAGE_TYPE.FILE, "/storage/emulated/0/DCIM/Camera/20190616_233731.jpg");  //1m
        listenerThread.write(SettingValue.BT_MESSAGE_TYPE.FILE, "/storage/emulated/0/PantaSCAN/XXXX/Original/00001.jpg"); //500k
    }
    @Override
    protected void onDestroy() {
        try {
            serverThread.interrupt();
            listenerThread.interrupt();
            listenerThread.interrupt();
            socket.close();
        } catch(Exception e) { }

        super.onDestroy();
    }

    //inner class////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public class ServerThread extends Thread{
        @Override
        public void run() {
            try {                
                serverSocket = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("SERVER",SettingValue.BT_UUID);
                showText("\nCreated sever socket.\nWaiting client.\n");
                
                socket = serverSocket.accept();
                showText("Client connected.\n");

                listenerThread = new ListenerThread(socket);
                listenerThread.start();

            } catch (IOException e) {
                Log.e("ServerThread", e.getMessage());
            }
        }//run() ..

        public void showText(final String msg){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tvLog.append(msg);
                }
            });
        }

    }//ServerThread

    public class ListenerThread extends Thread {

        protected BluetoothSocket mSocket;
        protected InputStream inStream;
        protected OutputStream outStream;

        private int nSendingType = 0; //0 length, 1 data
        private int nDataSize = 0;

        public ListenerThread(BluetoothSocket socket) {
            showText("ListenerThread will run.\n");
            mSocket = socket;

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try {
                tmpIn = mSocket.getInputStream();
                tmpOut = mSocket.getOutputStream();
            } catch (IOException e) {
                Log.e("ListenerThread", e.getMessage());
            }

            inStream = tmpIn;
            outStream = tmpOut;
        }

        public void run() {
            byte[] buffer;  // buffer store for the stream

            showText("ListenerThread is waiting.\n");

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                // Read from the InputStream
                buffer = new byte[SettingValue.BT_SEND_DATABUFFER_SIZE];

                try {
                    if(nSendingType == 0)
                    {
                        //Log.e("nSendingType", Integer.toString(nSendingType));
                        inStream.read(buffer);
                        ByteArrayInputStream byteIn = new ByteArrayInputStream(buffer);
                        nDataSize = (int)(new ObjectInputStream(byteIn)).readObject();
                        nSendingType = 1;

                        //Log.e("nDataSize", Integer.toString(nDataSize));
                    }
                    else
                    {
                        int byteNo = 0;
                        int writeByte = 0;
                        int bufferSize = nDataSize;

                        Log.e("elseFileDataSize", Integer.toString(nDataSize));
                        while (nDataSize != writeByte)
                        {
                            byteNo = inStream.read(buffer, writeByte, bufferSize);
                            writeByte += byteNo;
                            bufferSize = bufferSize - byteNo;

                            Log.e("writeByte", Integer.toString(writeByte));
                            Log.e("byteNo", Integer.toString(byteNo));
                        }

                        ByteArrayInputStream byteIn = new ByteArrayInputStream(buffer);
                        BlueToothData data = (BlueToothData)(new ObjectInputStream(byteIn)).readObject();

                        //Message send
                        Message msg = new Message();
                        msg.what = 1; 
                        msg.obj = (BlueToothData)data;
                        listenerHandler.sendMessage(msg);

                        nSendingType = 0;
                        nDataSize = 0;
                    }

                } catch (Exception e) {
                    Log.e("ListenerThread run", e.getMessage());
                    break;
                }
            }
        }        
        public void write(SettingValue.BT_MESSAGE_TYPE message_type, String text) {

            try {
                BlueToothData data  = new BlueToothData();
                byte[] buffer = new byte[10240000]; //10M

                switch (message_type)
                {
                    case TEXT : //SettingValue.BT_MESSAGE_TYPE.TEXT  enum은 값만 쓰면됨.
                        Log.d("write", "write: Writing to outputstream: " + text);

                        data.setMessage_type(message_type);
                        data.setData(text.getBytes());

                        break;
                    case FILE:                        
                        try{
                            FileInputStream fis = new FileInputStream(text);
                            BufferedInputStream bis = new BufferedInputStream(fis);

                            int length = bis.read(buffer);

                            Log.d("file", "start to send file.");

                            data = new BlueToothData();
                            data.setMessage_type(SettingValue.BT_MESSAGE_TYPE.FILE);
                            data.setFileName(text);
                            data.setData(buffer);

                        } catch (Exception e) {
                            Log.e("write", "file read Error. " + e.getMessage() );
                        }
                        break;
                }
               
                try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                    try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
                        oos.writeObject(data);
                        showText(Integer.toString(baos.toByteArray().length)+ "\n");

                        //////////////////////////////////
                        //send byte length.
                        ByteArrayOutputStream baosL = new ByteArrayOutputStream();
                        ObjectOutputStream oosL = new ObjectOutputStream(baosL);
                        oosL.writeObject(baos.toByteArray().length);

                        showText(String.valueOf(baosL.toByteArray().length) + "\n");
                        outStream.write(baosL.toByteArray());
                        outStream.flush();
                        //send byte length.
                        //////////////////////////////////


                        //send main data.
                        outStream.write(baos.toByteArray());
                        outStream.flush();

                    } catch (Exception e) {
                        Log.e("write", "ObjectOutputStream Error. " + e.getMessage());
                    }
                }
                catch(Exception e)
                {
                    Log.e("write", "ByteArrayOutputStream Error. " + e.getMessage() );
                }
                //data send
            } catch (Exception e) {
                Log.e("write", "write: Error writing to output stream. " + e.getMessage() );
            }
        }

        public void showText(final String msg){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    tvLog.append(msg);
                }
            });
        }

    }//ListenerThread

    //inner class////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}

*NorangActivity는 기본 Activity사용하면 됨. 

이것으로 인한 듣보잡 메서드는 삭제 하면 잘 돌아 갈 것임...

 

Marshmallow 6.0에서만 테스트 되었음. 그 이외의 버전은... 안될 수 있음... 

반응형

'Android' 카테고리의 다른 글

Android Barcode Create  (555) 2021.03.17
Bluetooth file & text transfer #3 client  (4) 2021.03.17
Bluetooth file & text transfer #1 etc  (6) 2021.03.17
Android ListView Sorting  (6) 2021.01.03
Android Error Message  (2) 2021.01.01

댓글