首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >无法停止服务-空对象引用错误- Android

无法停止服务-空对象引用错误- Android
EN

Stack Overflow用户
提问于 2018-08-16 08:37:41
回答 2查看 806关注 0票数 0

当我在水平或垂直视图中启动应用程序时,只要我旋转屏幕,应用程序就可以正常运行,它就会崩溃,并出现以下错误。从未使用过串口或Android服务。

Error:java.lang.RuntimeException:无法停止服务com.xxx.testing.UsbService@1aba8fa1: java.lang.NullPointerException:尝试对空对象引用调用虚方法'void com.felhr.usbserial.UsbSerialDevice.close()‘

在com.xxx.testing.UsbService.onDestroy(UsbService.java:92)

我们将非常感谢您的帮助。谢谢

错误

代码语言:javascript
复制
--------- beginning of crash
08-15 17:23:30.475 5966-5966/com.xxx /AndroidRuntime: FATAL EXCEPTION: main
    Process: com.xxx t, PID: 5966
    java.lang.RuntimeException: Unable to stop service com.xxx.testing.UsbService@1aba8fa1: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.felhr.usbserial.UsbSerialDevice.close()' on a null object reference
        at android.app.ActivityThread.handleStopService(ActivityThread.java:2911)
        at android.app.ActivityThread.access$2200(ActivityThread.java:144)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1381)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.felhr.usbserial.UsbSerialDevice.close()' on a null object reference
        at com.xxx.testing.UsbService.onDestroy(UsbService.java:92)
        at android.app.ActivityThread.handleStopService(ActivityThread.java:2894)

USB服务

代码语言:javascript
复制
@Override
public void onCreate() {
    this.context = this;
    serialPortConnected = false;
    UsbService.SERVICE_CONNECTED = true;
    setFilter();
    usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    findSerialPortDevice();
}

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

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    return START_NOT_STICKY;
}

@Override
public void onDestroy() {
    unregisterReceiver(usbReceiver);
    serialPort.close();
    UsbService.SERVICE_CONNECTED = false;
    super.onDestroy();
}

private class ConnectionThread extends Thread {
    @Override
    public void run() {
        serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
        if (serialPort != null) {
            if (serialPort.open()) {
                serialPort.setBaudRate(BAUD_RATE);
                serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                serialPort.read(mCallback);
                isReadyToSend = true;
                // Everything went as expected. Send an intent to MainActivity
                Intent intent = new Intent(ACTION_USB_READY);
                context.sendBroadcast(intent);
            } else {
                // Serial port could not be opened, maybe an I/O error or if CDC driver was chosen, it does not really fit
                // Send an Intent to Main Activity
                if (serialPort instanceof CDCSerialDevice) {
                    Intent intent = new Intent(ACTION_CDC_DRIVER_NOT_WORKING);
                    context.sendBroadcast(intent);
                } else {
                    Intent intent = new Intent(ACTION_USB_DEVICE_NOT_WORKING);
                    context.sendBroadcast(intent);
                }
            }
        } else {
            // No driver for given device, even generic CDC driver could not be loaded
            Intent intent = new Intent(ACTION_USB_NOT_SUPPORTED);
            context.sendBroadcast(intent);
        }
    }
}

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

private void setFilter() {
    IntentFilter filter = new IntentFilter();
    filter.addAction(ACTION_USB_PERMISSION);
    filter.addAction(ACTION_USB_DETACHED);
    filter.addAction(ACTION_USB_ATTACHED);
    registerReceiver(usbReceiver, filter);
}

private void requestUserPermission() {
    PendingIntent mPendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
    usbManager.requestPermission(device, mPendingIntent);
}

public class UsbBinder extends Binder {
    public UsbService getService() {
        return UsbService.this;
    }
}

private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context arg0, Intent arg1) {
        if (arg1.getAction().equals(ACTION_USB_PERMISSION)) {
            boolean granted = arg1.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
            if (granted) // User accepted our USB connection. Try to open the device as a serial port
            {
                Intent intent = new Intent(ACTION_USB_PERMISSION_GRANTED);
                arg0.sendBroadcast(intent);
                connection = usbManager.openDevice(device);
                serialPortConnected = true;
                new ConnectionThread().run();
            } else // User not accepted our USB connection. Send an Intent to the Main Activity
            {
                Intent intent = new Intent(ACTION_USB_PERMISSION_NOT_GRANTED);
                arg0.sendBroadcast(intent);
            }
        } else if (arg1.getAction().equals(ACTION_USB_ATTACHED)) {
            if (!serialPortConnected)
                findSerialPortDevice(); // A USB device has been attached. Try to open it as a Serial port
        } else if (arg1.getAction().equals(ACTION_USB_DETACHED)) {
            // Usb device was disconnected. send an intent to the Main Activity
            Intent intent = new Intent(ACTION_USB_DISCONNECTED);
            arg0.sendBroadcast(intent);
            serialPortConnected = false;
            serialPort.close();
        }
    }
};

private void findSerialPortDevice() {
    // This snippet will try to open the first encountered usb device connected, excluding usb root hubs
    HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
    if (!usbDevices.isEmpty()) {
        boolean keep = true;
        for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
            device = entry.getValue();
            int deviceVID = device.getVendorId();
            int devicePID = device.getProductId();
            String title = String.format("Vendor %s Product %s", device.getVendorId(), device.getProductId());
            Log.d("USB", "Found main Device: " + deviceVID + " " + devicePID);

            if (deviceVID != 0x1d6b && (devicePID != 0x0001 || devicePID != 0x0002 || devicePID != 0x0003)) {
                // There is a device connected to our Android device. Try to open it as a Serial Port.
                requestUserPermission();
                keep = false;
            } else {
                connection = null;
                device = null;
            }

            if (!keep)
                break;
        }
        if (!keep) {
            // There is no USB devices connected (but usb host were listed). Send an intent to MainActivity.
            Intent intent = new Intent(ACTION_NO_USB);
            sendBroadcast(intent);
        }
    } else {
        // There is no USB devices connected. Send an intent to MainActivity
        Intent intent = new Intent(ACTION_NO_USB);
        sendBroadcast(intent);
    }
}

ACtivity

代码语言:javascript
复制
public class splash_screen extends AppCompatActivity {

TextView text100, text200, text300, display;
Layout timer1;
// int time= 3600000*8;
public String data;
private UsbService usbService;
private EditText editText;
private MyHandler mHandler;
public StringBuilder stringBuilder = new StringBuilder();
//long time = 3600000 * 10;
long  time = 20000;
private long result;
private long result2;
static final String STATE_USER = "user";
private String mUser;
@Override
protected void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    super.onCreate(savedInstanceState);
    setContentView(R.layout.splash_screen);
    FullScreencall();

    mHandler = new MyHandler(splash_screen.this);


    int mUIFlag = View.SYSTEM_UI_FLAG_LOW_PROFILE
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
    getWindow().getDecorView().setSystemUiVisibility(mUIFlag);

    text100 = (TextView) findViewById(R.id.tv_hour);
    text200 = (TextView) findViewById(R.id.tv_minute);
    text300 = (TextView) findViewById(R.id.tv_second);

    View someView1 = findViewById(R.id.timer1);
    View someView2 = findViewById(R.id.timer2);
    View someView3 = findViewById(R.id.timer3);

    someView1.setBackgroundColor(Color.parseColor("#000000"));
    someView2.setBackgroundColor(Color.parseColor("#000000"));
    someView3.setBackgroundColor(Color.parseColor("#000000"));

    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mUser = savedInstanceState.getString(STATE_USER);
    } else {
        // Probably initialize members with default values for a new instance
        mUser = "NewUser";
    }

}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putString(STATE_USER, mUser);
    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

public void FullScreencall() {
    if(Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api


        int mUIFlag = View.SYSTEM_UI_FLAG_LOW_PROFILE
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN;


        getWindow().getDecorView().setSystemUiVisibility(mUIFlag);

    } else if(Build.VERSION.SDK_INT >= 19) {
        //for new api versions.
        View decorView = getWindow().getDecorView();
        // Hide both the navigation bar and the status bar.
        // SYSTEM_UI_FLAG_FULLSCREEN is only available on Android 4.1 and higher, but as
        // a general rule, you should design your app to hide the status bar whenever you
        // hide the navigation bar.
        int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;

        decorView.setSystemUiVisibility(uiOptions);


    }
}

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getAction()) {
            case UsbService.ACTION_USB_PERMISSION_GRANTED: // USB PERMISSION GRANTED
                //Toast.makeText(context, "USB Ready", Toast.LENGTH_SHORT).show();
                break;
            case UsbService.ACTION_USB_PERMISSION_NOT_GRANTED: // USB PERMISSION NOT GRANTED
                Toast.makeText(context, "USB Permission not granted", Toast.LENGTH_SHORT).show();
                break;
            case UsbService.ACTION_NO_USB: // NO USB CONNECTED
                // Toast.makeText(context, "No USB connected", Toast.LENGTH_SHORT).show();
                break;
            case UsbService.ACTION_USB_DISCONNECTED: // USB DISCONNECTED
                Toast.makeText(context, "USB disconnected", Toast.LENGTH_SHORT).show();
                break;
            case UsbService.ACTION_USB_NOT_SUPPORTED: // USB NOT SUPPORTED
                Toast.makeText(context, "USB device not supported", Toast.LENGTH_SHORT).show();
                break;
        }


    }
};

private void startService(Class<?> service, ServiceConnection serviceConnection, Bundle extras) {

    Intent serviceIntent = new Intent(this, UsbService.class);
    this.startService(serviceIntent);
    startService(serviceIntent);

    if (!UsbService.SERVICE_CONNECTED) {
        Intent startService = new Intent(this, UsbService.class);
        if (extras != null && !extras.isEmpty()) {
            Set<String> keys = extras.keySet();
            for (String key : keys) {
                String extra = extras.getString(key);
                startService.putExtra(key, extra);
            }
        }
        startService(startService);
    }
    Intent bindingIntent = new Intent(this, service);
    bindService(bindingIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}

private final ServiceConnection usbConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName arg0, IBinder arg1) {
        usbService = ((UsbService.UsbBinder) arg1).getService();
        usbService.setHandler(mHandler);
        usbService.sendATGetACC();


    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        usbService = null;
    }
};

@Override
public void onResume() {
    super.onResume();
    setFilters();  // Start listening notifications from UsbService
    startService(UsbService.class, usbConnection, null); // Start UsbService(if it was not started before) and Bind it
}

@Override
public void onPause() {
    try {
        unregisterReceiver(mUsbReceiver);
        unbindService(usbConnection);
    } catch (IllegalArgumentException ex) {
    }
    super.onPause();

}

@Override
public void onDestroy() {
    try {
        if (mUsbReceiver != null)
            unregisterReceiver(mUsbReceiver);
    } catch (Exception e) {
    }
    stopService(new Intent(splash_screen.this, UsbService.class));
    super.onDestroy();
}


private void setFilters() {
    IntentFilter filter = new IntentFilter();
    filter.addAction(UsbService.ACTION_USB_PERMISSION_GRANTED);
    filter.addAction(UsbService.ACTION_NO_USB);
    filter.addAction(UsbService.ACTION_USB_DISCONNECTED);
    filter.addAction(UsbService.ACTION_USB_NOT_SUPPORTED);
    filter.addAction(UsbService.ACTION_USB_PERMISSION_NOT_GRANTED);
    registerReceiver(mUsbReceiver, filter);
}

public class MyHandler extends Handler {

    private final WeakReference<splash_screen> mActivity;

    public MyHandler(splash_screen activity) {
        mActivity = new WeakReference<>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case UsbService.MESSAGE_FROM_SERIAL_PORT:
                String data = (String) msg.obj;
                if (data != null && !data.isEmpty()) {
                    Log.d("REPLY", "data value" + data);
                    mActivity.get().time(data);
                    break;
                } else {
                    Log.d("REPLY", "novalue");
                }
        }
    }
}

public void time(String data) {
    long sec = Integer.parseInt(data);
    Log.d("REPLY", "Recieved data" + sec);

    result = TimeUnit.SECONDS.toMillis(sec);
    Log.d("REPLY", "Result value" + result);

    result2 = time - result;
    Log.d("REPLY", "Result2 value" + result2);
    Log.d("REPLY", "Time value" + time);


    if (result >= time) {

        //usbService.sendATGetSTOP();
        Intent mainIntent = new Intent(splash_screen.this,
                MainActivity.class);
        mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        splash_screen.this.startActivity(mainIntent);
        splash_screen.this.finish();
    } else {
        if (result >= time) {

            // usbService.sendATGetSTOP();
            Intent mainIntent = new Intent(splash_screen.this,
                    MainActivity.class);
            mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

            splash_screen.this.startActivity(mainIntent);
            splash_screen.this.finish();

        } else {
            // Log.d("REPLY", "result2 value " + result2);
            splashScreenUseAsyncTask();

        }
    }
}


private void splashScreenUseAsyncTask() {
    // Create a AsyncTask object.
    final RetrieveDateTask retrieveDateTask = new RetrieveDateTask();
    retrieveDateTask.execute("", "", "");
    // Get splash image view object.
    final ImageView splashImageView = (ImageView) findViewById(R.id.logo_id);

    //for 5 Hours
    CountDownTimer countDownTimer = new CountDownTimer(result2, 1000) {
        @SuppressLint("DefaultLocale")
        @Override
        public void onTick(long l) {

            long Hours = l / (60 * 60 * 1000) % 24;
            long Minutes = l / (60 * 1000) % 60;
            long Seconds = l / 1000 % 60;

            // tv_days.setText(String.format("%02d", Days));
            text100.setText(String.format("%02d", Hours));
            text200.setText(String.format("%02d", Minutes));
            text300.setText(String.format("%02d", Seconds));

            AlphaAnimation anim = new AlphaAnimation(1.0f, 0.0f);
            anim.setDuration(500);
            anim.setRepeatCount(anim.INFINITE);
            anim.setRepeatMode(Animation.REVERSE);
            splashImageView.startAnimation(anim);


        }

        @Override
        public void onFinish() {

            if (!retrieveDateTask.isAsyncTaskComplete()) {
                this.start();
            }
        }
    };
    // Start the count down timer.
    countDownTimer.start();

}

// This is the async task class that get data from network.
@SuppressLint("StaticFieldLeak")
private class RetrieveDateTask extends AsyncTask<String, String, String> {

    // Indicate whether AsyncTask complete or not.
    private boolean asyncTaskComplete = false;

    public boolean isAsyncTaskComplete() {
        return asyncTaskComplete;
    }

    public void setAsyncTaskComplete(boolean asyncTaskComplete) {
        this.asyncTaskComplete = asyncTaskComplete;
    }

    // This method will be called before AsyncTask run.
    @Override
    protected void onPreExecute() {
        this.asyncTaskComplete = false;
    }

    // This method will be called when AsyncTask run.
    @Override
    protected String doInBackground(String... strings) {
        try {
            // Simulate a network operation which will last for 10 seconds.
            Thread currTread = Thread.currentThread();
            currTread.sleep(result2);

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            return null;
        }
    }

    // This method will be called after AsyncTask run.
    @Override
    protected void onPostExecute(String s) {
        //usbService.sendATGetSTOP();
        this.asyncTaskComplete = true;
        //usbService.sendATGetACC();
        // Start SplashScreenMainActivity.
        Intent mainIntent = new Intent(splash_screen.this,
                MainActivity.class);
        mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

        splash_screen.this.startActivity(mainIntent);
        splash_screen.this.finish();

    }
}

}

EN

回答 2

Stack Overflow用户

发布于 2018-08-16 09:06:29

当屏幕旋转时,它将重新创建活动。我建议检查onDestroy(),看看USB是否为空。然后,在create()中更改方向后进行调试,以查看是否也重新创建了USB。我们可以利用onSaveInstance()在方向改变之前保存一些数据。

https://developer.android.com/guide/topics/resources/runtime-changes

票数 0
EN

Stack Overflow用户

发布于 2019-06-20 20:41:55

在onDestroy()中使用以下代码:

代码语言:javascript
复制
if (serialPort != null){
        serialPort.close();
    }

而不是:

代码语言:javascript
复制
serialPort.close();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51868168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档