0

Android Due と Bluetooth HM-10 BLE モジュールを介してステッピング モーターを制御する Android アプリを開発しています。

これまでのところすべて動作していますが、一部のデバイスでアプリがクラッシュする問題があるようです。私の Nexus 5 と 7 では問題なく動作していますが、たとえば Samsung Galaxy S5 ではクラッシュし続けます。すべてのデバイスに Andoird 6.0.1 が搭載されているため、同等のはずです。

ユーザーから次のエラー レポートを受け取りました。

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattCharacteristic.setValue(byte[])' on a null object reference
    at pm.puremoco.BluetoothLeService.WriteValue(BluetoothLeService.java:70)
    at pm.puremoco.frag_moviesetlinear$3.onFinish(frag_moviesetlinear.java:266)
    at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:127)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:158)
    at android.app.ActivityThread.main(ActivityThread.java:7224)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

そのため、「onCreateView」で開いたときにエラーが発生しています。値を送信するコマンドがあります。

  mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");

ほぼ完全なフラグメントを次に示します。

public class frag_moviesetlinear extends Fragment {

    public static final String methodtocall = "ooo";
    private final static String TAG = DeviceControlFragment.class.getSimpleName();
    public AlertDialog alertTransmitData;
    public BluetoothLeService mBluetoothLeService; //TODO evtl. private
    public String methodcalled = "aaa";
    public String dataLineReceived;
    public long countDownTimerDelay = 200;
    public AlertDialog alertTimeTooShort;
    NumberPicker noPick1 = null;
    NumberPicker noPick2 = null;
    NumberPicker noPick3 = null;
    long alertTransmitDataLength = 21000;
    DeviceControlFragment devConFrag;
    double minTimeFactor = 0;
    TextView vid_maxSpeedU;
    TextView vid_maxSpeedV;
    TextView vid_maxSpeedW;
    TextView vid_maxSpeedX;
    TextView vid_maxSpeedY;
    TextView vid_maxSpeedZ;
    TextView vid_maxSpeedUspline;
    TextView vid_maxSpeedVspline;
    TextView vid_maxSpeedWspline;
    TextView vid_maxSpeedXspline;
    TextView vid_maxSpeedYspline;
    TextView vid_maxSpeedZspline;
    TextView txt_vidDuration;
    TextView txt_vidUpdateIntervall;
    TextView txt_minTime;
    int timeForCalculation = 0;
    int calculatedSpeedU = 0;
    int calculatedSpeedV = 0;
    int calculatedSpeedW = 0;
    int calculatedSpeedX = 0;
    int calculatedSpeedY = 0;
    int calculatedSpeedZ = 0;

    boolean movingHome = false;

    private String mDeviceAddress;
    private final ServiceConnection mServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
            if (!mBluetoothLeService.initialize()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
                getActivity().finish();
            }

            Log.e(TAG, "mBluetoothLeService is okay");
            //  Log.e(TAG, mDeviceAddress);
            // Automatically connects to the device upon successful start-up initialization.
            if (mDeviceAddress == "---") {

                Toast.makeText(getActivity(), "Bluetooth-Device not selected!", Toast.LENGTH_SHORT).show();
            } else {
                mBluetoothLeService.connect(mDeviceAddress);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBluetoothLeService = null;
        }
    };
    private String mDeviceName;
    private TextView mDataField;
    private Button btn_vidSplineStart;
    private Button btn_vidUpdateIntervalNeg;
    private Button btn_vidUpdateIntervalPos;
    private boolean mConnected = false;
    // Handles various events fired by the Service.
    // ACTION_GATT_CONNECTED: connected to a GATT server.
    // ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
    // ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
    // ACTION_DATA_AVAILABLE: received data from the device.  This can be a result of read
    //                        or notification operations.
    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {  //���ӳɹ�
                Log.e(TAG, "Only gatt, just wait");
            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { //�Ͽ�����
                mConnected = false;
                getActivity().invalidateOptionsMenu();
                // btnSend.setEnabled(false);

            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) //���Կ�ʼ�ɻ���
            {
                mConnected = true;
                // mDataField.setText("");

                //  ShowDialog();
                //btnSend.setEnabled(true);
                Log.e(TAG, "In what we need");

                getActivity().invalidateOptionsMenu();
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { //�յ�����
                Log.e(TAG, "RECV DATA");
                final String data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
                Log.e(TAG, data);
                if (data != null && data.substring(0, 1).equals("#") && data.substring(data.length() - 1).equals("$")) {
                    //  if (mDataField.length() > 500)
                    //      mDataField.setText("");
                    //  mDataField.append(data);
                    dataLineReceived = data.substring(1, data.length() - 1);
                    ActionHandlerDataReceived();
                }
            }
        }
    };

    private static IntentFilter makeGattUpdateIntentFilter() {                        //ע����յ��¼�
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        intentFilter.addAction(BluetoothDevice.ACTION_UUID);
        return intentFilter;
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //   getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        final Intent intent = getActivity().getIntent();
        // mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
        //  mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
        mDeviceAddress = variables.BluetoothAddress;
        mDeviceName = variables.BluetoothName;

        methodcalled = intent.getStringExtra(methodtocall);


        Intent gattServiceIntent = new Intent(getActivity(), BluetoothLeService.class);
        Log.d(TAG, "Try to bindService=" + getActivity().bindService(gattServiceIntent, mServiceConnection, getActivity().BIND_AUTO_CREATE));

        getActivity().registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
        getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);




    }

    @Override
    public void onPause() {
        super.onPause();
        try {
            getActivity().unregisterReceiver(mGattUpdateReceiver);
        }
        catch(Exception e){

        }

        try {
            getActivity().unbindService(mServiceConnection);
        }
        catch(Exception e){

        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        Log.d(TAG, "We are in destroy");
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View layout = inflater.inflate(R.layout.setmovie, null);

        vid_maxSpeedU = (TextView) layout.findViewById(R.id.vid_maxSpeedU);
        vid_maxSpeedU.setText(String.valueOf(variables.speedU));
        vid_maxSpeedV = (TextView) layout.findViewById(R.id.vid_maxSpeedV);
        vid_maxSpeedV.setText(String.valueOf(variables.speedV));
        vid_maxSpeedW = (TextView) layout.findViewById(R.id.vid_maxSpeedW);
        vid_maxSpeedW.setText(String.valueOf(variables.speedW));
        vid_maxSpeedX = (TextView) layout.findViewById(R.id.vid_maxSpeedX);
        vid_maxSpeedX.setText(String.valueOf(variables.speedX));
        vid_maxSpeedY = (TextView) layout.findViewById(R.id.vid_maxSpeedY);
        vid_maxSpeedY.setText(String.valueOf(variables.speedY));
        vid_maxSpeedZ = (TextView) layout.findViewById(R.id.vid_maxSpeedZ);
        vid_maxSpeedZ.setText(String.valueOf(variables.speedZ));

        double duration = 3700 * (double) variables.vidUpdateIntervall / 1000;
        txt_vidUpdateIntervall = (TextView) layout.findViewById(R.id.txt_vidUpdateIntervall);
        txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));
        txt_vidDuration = (TextView) layout.findViewById(R.id.txt_vidDuration);
        txt_vidDuration.setText(String.format("%.2f", duration) + " s");

        vid_maxSpeedUspline = (TextView) layout.findViewById(R.id.vid_maxSpeedUspline);
        vid_maxSpeedVspline = (TextView) layout.findViewById(R.id.vid_maxSpeedVspline);
        vid_maxSpeedWspline = (TextView) layout.findViewById(R.id.vid_maxSpeedWspline);
        vid_maxSpeedXspline = (TextView) layout.findViewById(R.id.vid_maxSpeedXspline);
        vid_maxSpeedYspline = (TextView) layout.findViewById(R.id.vid_maxSpeedYspline);
        vid_maxSpeedZspline = (TextView) layout.findViewById(R.id.vid_maxSpeedZspline);

        txt_minTime = (TextView) layout.findViewById(R.id.txt_minTime);


        btn_vidSplineStart = (Button) layout.findViewById(R.id.btn_vidSplineStart);
        btn_vidSplineStart.setOnClickListener(new event_btn_vidSplineStart());


        btn_vidUpdateIntervalPos = (Button) layout.findViewById(R.id.btn_vidUpdateIntervalPos);
        btn_vidUpdateIntervalPos.setOnClickListener(new event_btn_vidUpdateIntervalPos());
        btn_vidUpdateIntervalNeg = (Button) layout.findViewById(R.id.btn_vidUpdateIntervalNeg);
        btn_vidUpdateIntervalNeg.setOnClickListener(new event_btn_vidUpdateIntervalNeg());

        //-----start-button------
        minTimeFactor = 0;

        timeForCalculation = variables.vidUpdateIntervall;


        new CountDownTimer(countDownTimerDelay * 1, 1) {

            public void onTick(long millisUntilFinished) {

            }

            public void onFinish() {
                mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
            }
        }.start();

        new CountDownTimer(countDownTimerDelay * 2, 1) {

            public void onTick(long millisUntilFinished) {

            }

            public void onFinish() {
                mBluetoothLeService.WriteValue("2000_" + String.valueOf(variables.linearWithFade) + "#");
            }
        }.start();

        //-----start-button------

        transmitDataAlert("calculation");





        return layout;
    }


    private void ActionHandlerDataReceived() {


        String variable;
        String value;


        String[] parts = dataLineReceived.split("_"); // escape .
        variable = parts[0];
        value = parts[1];

        switch (variable) {
            case "vidMaxSpeedU":
                vid_maxSpeedUspline.setText(String.valueOf(value));
                variables.vid_maxSpeedUspline = Integer.parseInt(value);
                calculatedSpeedU = Integer.parseInt(value);
                if (Integer.parseInt(value) > variables.speedU) {
                    vid_maxSpeedUspline.setTextColor(Color.parseColor("#FFFF3434"));
                } else {
                    vid_maxSpeedUspline.setTextColor(Color.parseColor("#FF14AA00"));
                }
                double FactorU = Double.valueOf(value) / variables.speedU;
                if (minTimeFactor < FactorU) {
                    minTimeFactor = FactorU;
                }

                break;
            case "vidMaxSpeedV":
                vid_maxSpeedVspline.setText(String.valueOf(value));
                variables.vid_maxSpeedVspline = Integer.parseInt(value);
                calculatedSpeedV = Integer.parseInt(value);
                if (Integer.parseInt(value) > variables.speedV) {
                    vid_maxSpeedVspline.setTextColor(Color.parseColor("#FFFF3434"));
                } else {
                    vid_maxSpeedVspline.setTextColor(Color.parseColor("#FF14AA00"));
                }
                double FactorV = Double.valueOf(value) / variables.speedV;
                if (minTimeFactor < FactorV) {
                    minTimeFactor = FactorV;
                }
                break;
            case "vidMaxSpeedW":
                vid_maxSpeedWspline.setText(String.valueOf(value));
                variables.vid_maxSpeedWspline = Integer.parseInt(value);
                calculatedSpeedW = Integer.parseInt(value);
                if (Integer.parseInt(value) > variables.speedW) {
                    vid_maxSpeedWspline.setTextColor(Color.parseColor("#FFFF3434"));
                } else {
                    vid_maxSpeedWspline.setTextColor(Color.parseColor("#FF14AA00"));
                }
                double FactorW = Double.valueOf(value) / variables.speedW;
                if (minTimeFactor < FactorW) {
                    minTimeFactor = FactorW;
                }
                break;
            case "vidMaxSpeedX":
                vid_maxSpeedXspline.setText(String.valueOf(value));
                variables.vid_maxSpeedXspline = Integer.parseInt(value);
                calculatedSpeedX = Integer.parseInt(value);
                if (Integer.parseInt(value) > variables.speedX) {
                    vid_maxSpeedXspline.setTextColor(Color.parseColor("#FFFF3434"));
                } else {
                    vid_maxSpeedXspline.setTextColor(Color.parseColor("#FF14AA00"));
                }
                double FactorX = Double.valueOf(value) / variables.speedX;
                if (minTimeFactor < FactorX) {
                    minTimeFactor = FactorX;
                }
                break;
            case "vidMaxSpeedY":
                vid_maxSpeedYspline.setText(String.valueOf(value));
                variables.vid_maxSpeedYspline = Integer.parseInt(value);
                calculatedSpeedY = Integer.parseInt(value);
                if (Integer.parseInt(value) > variables.speedY) {
                    vid_maxSpeedYspline.setTextColor(Color.parseColor("#FFFF3434"));
                } else {
                    vid_maxSpeedYspline.setTextColor(Color.parseColor("#FF14AA00"));
                }
                double FactorY = Double.valueOf(value) / variables.speedY;
                if (minTimeFactor < FactorY) {
                    minTimeFactor = FactorY;
                }
                break;
            case "vidMaxSpeedZ":
                vid_maxSpeedZspline.setText(String.valueOf(value));
                variables.vid_maxSpeedZspline = Integer.parseInt(value);
                calculatedSpeedZ = Integer.parseInt(value);
                if (Integer.parseInt(value) > variables.speedZ) {
                    vid_maxSpeedZspline.setTextColor(Color.parseColor("#FFFF3434"));
                } else {
                    vid_maxSpeedZspline.setTextColor(Color.parseColor("#FF14AA00"));
                }
                double FactorZ = Double.valueOf(value) / variables.speedZ;
                if (minTimeFactor < FactorZ) {
                    minTimeFactor = FactorZ;
                }
                alertTransmitData.dismiss();

                double vidMin = Math.ceil(minTimeFactor * timeForCalculation);
                variables.vidMinIntervall = (int) vidMin;
                //txt_minTime.setText(String.valueOf(variables.vidMinIntervall));

                double duration = (3700 * (double) variables.vidMinIntervall) / 1000;
                txt_minTime.setText(String.format("%.2f", duration) + " s");

                if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
                    btn_vidSplineStart.setEnabled(true);
                }
                break;

            case "movieFinished":
                btn_vidSplineStart.setText("Move home");
                btn_vidSplineStart.setEnabled(true);
                movingHome = true;
                alertTransmitData.dismiss();
                break;
            case "movieHome":
                btn_vidSplineStart.setText("Start");
                btn_vidSplineStart.setEnabled(true);
                alertTransmitData.dismiss();
                break;




        }

    }

    void calculateNewSpeeds() {
        //--------------U-Axis-----------------
        if (variables.vid_maxSpeedUspline != 0) {
            variables.vid_maxSpeedUspline = (timeForCalculation * calculatedSpeedU) / variables.vidUpdateIntervall;
            vid_maxSpeedUspline.setText(String.valueOf(variables.vid_maxSpeedUspline));

            if (variables.vid_maxSpeedUspline > variables.speedU) {
                vid_maxSpeedUspline.setTextColor(Color.parseColor("#FFFF3434"));
            } else {
                vid_maxSpeedUspline.setTextColor(Color.parseColor("#FF14AA00"));
            }
        }
        //--------------V-Axis-----------------
        if (variables.vid_maxSpeedVspline != 0) {
            variables.vid_maxSpeedVspline = (timeForCalculation * calculatedSpeedV) / variables.vidUpdateIntervall;
            vid_maxSpeedVspline.setText(String.valueOf(variables.vid_maxSpeedVspline));

            if (variables.vid_maxSpeedVspline > variables.speedV) {
                vid_maxSpeedVspline.setTextColor(Color.parseColor("#FFFF3434"));
            } else {
                vid_maxSpeedVspline.setTextColor(Color.parseColor("#FF14AA00"));
            }
        }
        //--------------W-Axis-----------------
        if (variables.vid_maxSpeedWspline != 0) {
            variables.vid_maxSpeedWspline = (timeForCalculation * calculatedSpeedW) / variables.vidUpdateIntervall;
            vid_maxSpeedWspline.setText(String.valueOf(variables.vid_maxSpeedWspline));

            if (variables.vid_maxSpeedWspline > variables.speedW) {
                vid_maxSpeedWspline.setTextColor(Color.parseColor("#FFFF3434"));
            } else {
                vid_maxSpeedWspline.setTextColor(Color.parseColor("#FF14AA00"));
            }
        }
        //--------------X-Axis-----------------
        if (variables.vid_maxSpeedXspline != 0) {
            variables.vid_maxSpeedXspline = (timeForCalculation * calculatedSpeedX) / variables.vidUpdateIntervall;
            vid_maxSpeedXspline.setText(String.valueOf(variables.vid_maxSpeedXspline));

            if (variables.vid_maxSpeedXspline > variables.speedX) {
                vid_maxSpeedXspline.setTextColor(Color.parseColor("#FFFF3434"));
            } else {
                vid_maxSpeedXspline.setTextColor(Color.parseColor("#FF14AA00"));
            }
        }
        //--------------Y-Axis-----------------
        if (variables.vid_maxSpeedYspline != 0) {
            variables.vid_maxSpeedYspline = (timeForCalculation * calculatedSpeedY) / variables.vidUpdateIntervall;
            vid_maxSpeedYspline.setText(String.valueOf(variables.vid_maxSpeedYspline));

            if (variables.vid_maxSpeedYspline > variables.speedY) {
                vid_maxSpeedYspline.setTextColor(Color.parseColor("#FFFF3434"));
            } else {
                vid_maxSpeedYspline.setTextColor(Color.parseColor("#FF14AA00"));
            }
        }
        //--------------Z-Axis-----------------
        if (variables.vid_maxSpeedZspline != 0) {
            variables.vid_maxSpeedZspline = (timeForCalculation * calculatedSpeedZ) / variables.vidUpdateIntervall;
            vid_maxSpeedZspline.setText(String.valueOf(variables.vid_maxSpeedZspline));

            if (variables.vid_maxSpeedZspline > variables.speedZ) {
                vid_maxSpeedZspline.setTextColor(Color.parseColor("#FFFF3434"));
            } else {
                vid_maxSpeedZspline.setTextColor(Color.parseColor("#FF14AA00"));
            }
        }


    }

    public void alert_TimeTooShort(int errorCase, int movieLengthSecondsNEW) {
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                getActivity());

        // set title
        alertDialogBuilder.setTitle("Error");

        String errorMessage = "error";




        // set dialog message
        alertDialogBuilder
                .setMessage(errorMessage)
                .setCancelable(false);

        alertDialogBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                // continue with delete
            }
        });

        // create alert dialog
        alertTimeTooShort = alertDialogBuilder.create();

        // show it
        alertTimeTooShort.show();


    }

    public void transmitDataAlert(String type) {
        LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
        View promptView = layoutInflater.inflate(R.layout.alert_transmitdata, null);
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
        alertDialogBuilder.setView(promptView);
        final ProgressBar progressbar = (ProgressBar) promptView.findViewById(R.id.progressBar_transmitData);
        final TextView txt_PleaseWait = (TextView) promptView.findViewById(R.id.txt_PleaseWait);
        final TextView txt_timeRemainVideo = (TextView) promptView.findViewById(R.id.txt_timeRemainVideo);
        final TextView txt_timeRemainVideoTXT = (TextView) promptView.findViewById(R.id.txt_timeRemainVideoTXT);



        new CountDownTimer(alertTransmitDataLength, 1) {

            public void onTick(long millisUntilFinished) {
                int longtointRemain = (int) millisUntilFinished;
                int longtointFull = (int) alertTransmitDataLength;
                int percentprogress = 100 - ((100 * longtointRemain) / longtointFull);
                progressbar.setProgress(percentprogress);

                float duration = (float) millisUntilFinished/1000;
                txt_timeRemainVideo.setText(String.format("%.1f", duration) + " s");
            }

            public void onFinish() {

            }
        }.start();


        }

        alertDialogBuilder.setCancelable(false);

        alertTransmitData = alertDialogBuilder.create();
        alertTransmitData.show();
    }

    class event_btn_vidSplineStart implements View.OnClickListener {


        @Override
        public void onClick(View v) {


            btn_vidSplineStart.setEnabled(false);
            btn_vidSplineStart.setText("Moving...");


            new CountDownTimer(countDownTimerDelay * 1, 1) {

                public void onTick(long millisUntilFinished) {

                }

                public void onFinish() {
                    //MotionMode
                    mBluetoothLeService.WriteValue("1900_" + String.valueOf(variables.vidUpdateIntervall) + "#");
                }
            }.start();

            new CountDownTimer(countDownTimerDelay * 2, 1) {

                public void onTick(long millisUntilFinished) {

                }

                public void onFinish() {
                    //MotionMode
                    mBluetoothLeService.WriteValue("1110_0#");
                }
            }.start();

            alertTransmitDataLength = (long) variables.vidUpdateIntervall*3700;

            if(movingHome==true){
                transmitDataAlert("moveHome");
                movingHome=false;
            }
            else {
                transmitDataAlert("videomove");
            }
        }


    }

    class event_btn_vidUpdateIntervalPos implements View.OnClickListener {


        @Override
        public void onClick(View v) {
            variables.vidUpdateIntervall++;
            double duration = (3700 * (double) variables.vidUpdateIntervall) / 1000;
            txt_vidDuration.setText(String.format("%.2f", duration) + " s");

            txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));

            calculateNewSpeeds();

            if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
                btn_vidSplineStart.setEnabled(true);
            }
            else{
                btn_vidSplineStart.setEnabled(false);

            }
        }
    }

    class event_btn_vidUpdateIntervalNeg implements View.OnClickListener {


        @Override
        public void onClick(View v) {

            if (variables.vidUpdateIntervall > 1) {
                variables.vidUpdateIntervall--;
            }
            double duration = (3700 * (double) variables.vidUpdateIntervall) / 1000;
            txt_vidDuration.setText(String.format("%.2f", duration) + " s");

            txt_vidUpdateIntervall.setText(String.valueOf(variables.vidUpdateIntervall));


            calculateNewSpeeds();

            if(variables.vidMinIntervall<=variables.vidUpdateIntervall) {
                btn_vidSplineStart.setEnabled(true);
            }
            else{
                btn_vidSplineStart.setEnabled(false);

            }
        }


    }


}
4

1 に答える 1

1

HM-10 Bluetooth メーカーの Web サイトから取得した完全な BluetoothLeService は次のとおりです。

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import java.util.List;
import java.util.UUID;

/**
 * Service for managing connection and data communication with a GATT server hosted on a
 * given Bluetooth LE device.
 */
public class BluetoothLeService extends Service {
    private final static String TAG = BluetoothLeService.class.getSimpleName();

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothGatt mBluetoothGatt;

    public final static String ACTION_GATT_CONNECTED =
            "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED =
            "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED =
            "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
    public final static String ACTION_DATA_AVAILABLE =
            "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
    public final static String EXTRA_DATA =
            "com.example.bluetooth.le.EXTRA_DATA";

    public final static UUID UUID_NOTIFY =
            UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb");
    public final static UUID UUID_SERVICE =
            UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb");

    public BluetoothGattCharacteristic mNotifyCharacteristic;

    public void WriteValue(String strValue)
    {
            mNotifyCharacteristic.setValue(strValue.getBytes());
            mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic);

    }

    public void findService(List<BluetoothGattService> gattServices)
    {
        Log.i(TAG, "Count is:" + gattServices.size());
        for (BluetoothGattService gattService : gattServices)
        {
            Log.i(TAG, gattService.getUuid().toString());
            Log.i(TAG, UUID_SERVICE.toString());
            if(gattService.getUuid().toString().equalsIgnoreCase(UUID_SERVICE.toString()))
            {
                List<BluetoothGattCharacteristic> gattCharacteristics =
                        gattService.getCharacteristics();
                Log.i(TAG, "Count is:" + gattCharacteristics.size());
                for (BluetoothGattCharacteristic gattCharacteristic :
                        gattCharacteristics)
                {
                    if(gattCharacteristic.getUuid().toString().equalsIgnoreCase(UUID_NOTIFY.toString()))
                    {
                        Log.i(TAG, gattCharacteristic.getUuid().toString());
                        Log.i(TAG, UUID_NOTIFY.toString());
                        mNotifyCharacteristic = gattCharacteristic;
                        setCharacteristicNotification(gattCharacteristic, true);
                        broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
                        return;
                    }
                }
            }
        }
    }

    // Implements callback methods for GATT events that the app cares about.  For example,
    // connection change and services discovered.
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            Log.i(TAG, "oldStatus=" + status + " NewStates=" + newState);
            if(status == BluetoothGatt.GATT_SUCCESS)
            {

                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    intentAction = ACTION_GATT_CONNECTED;

                    broadcastUpdate(intentAction);
                    Log.i(TAG, "Connected to GATT server.");
                    // Attempts to discover services after successful connection.
                    Log.i(TAG, "Attempting to start service discovery:" +
                            mBluetoothGatt.discoverServices());
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    intentAction = ACTION_GATT_DISCONNECTED;
                    mBluetoothGatt.close();
                    mBluetoothGatt = null;
                    Log.i(TAG, "Disconnected from GATT server.");
                    broadcastUpdate(intentAction);
                }
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.w(TAG, "onServicesDiscovered received: " + status);
                findService(gatt.getServices());
            } else {
                if(mBluetoothGatt.getDevice().getUuids() == null)
                    Log.w(TAG, "onServicesDiscovered received: " + status);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            Log.e(TAG, "OnCharacteristicWrite");
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                                          int status)
        {
            Log.e(TAG, "OnCharacteristicWrite");
        }

        @Override
        public void onDescriptorRead(BluetoothGatt gatt,
                                     BluetoothGattDescriptor bd,
                                     int status) {
            Log.e(TAG, "onDescriptorRead");
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt,
                                      BluetoothGattDescriptor bd,
                                      int status) {
            Log.e(TAG, "onDescriptorWrite");
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int a, int b)
        {
            Log.e(TAG, "onReadRemoteRssi");
        }

        @Override
        public void onReliableWriteCompleted(BluetoothGatt gatt, int a)
        {
            Log.e(TAG, "onReliableWriteCompleted");
        }

    };

    private void broadcastUpdate(final String action) {
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    private void broadcastUpdate(final String action,
                                 final BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);

        // This is special handling for the Heart Rate Measurement profile.  Data parsing is
        // carried out as per profile specifications:
        // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
        // For all other profiles, writes the data formatted in HEX.
        final byte[] data = characteristic.getValue();
        if (data != null && data.length > 0) {
            //final StringBuilder stringBuilder = new StringBuilder(data.length);
            //for(byte byteChar : data)
            //    stringBuilder.append(String.format("%02X ", byteChar));
            //intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
            intent.putExtra(EXTRA_DATA, new String(data));
        }
        sendBroadcast(intent);
    }

    public class LocalBinder extends Binder {
        BluetoothLeService getService() {
            return BluetoothLeService.this;
        }
    }

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

    @Override
    public boolean onUnbind(Intent intent) {
        // After using a given device, you should make sure that BluetoothGatt.close() is called
        // such that resources are cleaned up properly.  In this particular example, close() is
        // invoked when the UI is disconnected from the Service.
        close();
        return super.onUnbind(intent);
    }

    private final IBinder mBinder = new LocalBinder();

    /**
     * Initializes a reference to the local Bluetooth adapter.
     *
     * @return Return true if the initialization is successful.
     */
    public boolean initialize() {
        // For API level 18 and above, get a reference to BluetoothAdapter through
        // BluetoothManager.
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Log.e(TAG, "Unable to initialize BluetoothManager.");
                return false;
            }
        }

        mBluetoothAdapter = mBluetoothManager.getAdapter();
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
            return false;
        }

        return true;
    }

    /**
     * Connects to the GATT server hosted on the Bluetooth LE device.
     *
     * @param address The device address of the destination device.
     *
     * @return Return true if the connection is initiated successfully. The connection result
     *         is reported asynchronously through the
     *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
     *         callback.
     */
    public boolean connect(final String address) {
        if (mBluetoothAdapter == null || address == null) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }
/*
        // Previously connected device.  Try to reconnect.
        if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
                && mBluetoothGatt != null) {
            Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
            if (mBluetoothGatt.connect()) {
                mConnectionState = STATE_CONNECTING;
                return true;
            } else {
                return false;
            }
        }
*/
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // We want to directly connect to the device, so we are setting the autoConnect
        // parameter to false.
        if(mBluetoothGatt != null)
        {
            mBluetoothGatt.close();
            mBluetoothGatt = null;
        }
        mBluetoothGatt = device.connectGatt(this.getApplication(), false, mGattCallback);
        //mBluetoothGatt.connect();

        Log.d(TAG, "Trying to create a new connection.");
        return true;
    }

    /**
     * Disconnects an existing connection or cancel a pending connection. The disconnection result
     * is reported asynchronously through the
     * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
     * callback.
     */
    public void disconnect() {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.disconnect();
    }

    /**
     * After using a given BLE device, the app must call this method to ensure resources are
     * released properly.
     */
    public void close() {
        /*
        if (mBluetoothGatt == null) {
            return;
        }
        mBluetoothGatt.close();
        mBluetoothGatt = null;
        */
    }

    /**
     * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
     * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
     * callback.
     *
     * @param characteristic The characteristic to read from.
     */
    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.readCharacteristic(characteristic);
    }

    /**
     * Enables or disables notification on a give characteristic.
     *
     * @param characteristic Characteristic to act on.
     * @param enabled If true, enable notification.  False otherwise.
     */
    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                              boolean enabled) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
/*
        // This is specific to Heart Rate Measurement.
        if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                    UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            mBluetoothGatt.writeDescriptor(descriptor);
        }
        */
    }

    /**
     * Retrieves a list of supported GATT services on the connected device. This should be
     * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
     *
     * @return A {@code List} of supported services.
     */
    public List<BluetoothGattService> getSupportedGattServices() {
        if (mBluetoothGatt == null) return null;

        return mBluetoothGatt.getServices();
    }
}
于 2016-07-28T16:52:00.683 に答える