英文:
Background service crash
问题
所以出现某种原因导致我的后台服务崩溃,而我不知道原因所在。
我的服务包含BLE,我从MainActivity中使用以下代码绑定到服务:
public void startBluetoothService() {
// 启动BLE服务
Log.d(TAG, "Starting BLE Service");
Intent gattServiceIntent = new Intent(this, BLE_Service.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Log.d(TAG, "Bluetooth is Enabled");
}
这段代码运行了,但是之后我得到了以下错误:
10-09 12:51:31.104 14007-14081/com.example.wrd I/ProviderInstaller: Installed default security provider GmsCore_OpenSSL
10-09 12:51:31.114 14007-14007/com.example.wrd D/AndroidRuntime: Shutting down VM
10-09 12:51:31.114 14007-14007/com.example.wrd E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.wrd, PID: 14007
java.lang.RuntimeException: Unable to instantiate service com.example.wrd.ble.BLE_Service: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3841)
at android.app.ActivityThread.access$2100(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
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)
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3838)
at android.app.ActivityThread.access$2100(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
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)
我的服务看起来是这样的:
public class BLE_Service extends Service {
// ... 其他部分的代码 ...
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public BLE_Service(Home home, long scanPeriod, int signalStrength) {
// 构造函数的实现
// ...
}
// ... 其他部分的代码 ...
}
你提到了在你的onStart()
中启动了服务,然后在onCreate()
中运行了 BLE_Service(this, 7500, -75)
,但是问题在于BLE_Service
的构造函数需要一个参数列表。可能的解决方法之一是,将这部分逻辑放到onServiceConnected()
回调中,以确保服务已经被正确绑定。这样做可以确保在构造函数中调用服务实例之前,onStart()
已经成功地绑定了服务。
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
// 这里是服务绑定成功的回调
BLE_Service.LocalBinder binder = (BLE_Service.LocalBinder) iBinder;
mBoundService = binder.getService();
mServiceBound = true;
// 这里可以执行启动服务的逻辑,确保服务已绑定后再运行
mBoundService.initialize(); // 例如这里初始化服务
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mServiceBound = false;
}
};
当你在onStart()
中绑定服务时,onServiceConnected()
将会在服务绑定成功时被调用。在这个回调中,你可以执行启动服务以及其他必要的逻辑,确保服务在使用之前已经准备好。
另外,确保在不再需要服务时解除绑定,可以在onStop()
中实现:
@Override
protected void onStop() {
super.onStop();
if (mServiceBound) {
unbindService(mServiceConnection);
mServiceBound = false;
}
}
这样可以避免内存泄漏和其他可能的问题。
英文:
So for some reason my background service crashes, and I don't know why.
So my service contains BLE, and I bind to the service from the MainActivity with:
public void startBluetoothService() {
// Start the BLE Service
Log.d(TAG, "Starting BLE Service");
Intent gattServiceIntent = new Intent(this, BLE_Service.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Log.d(TAG, "Bluetooth is Enabled");
}
This runs, but then I get the following error
10-09 12:51:31.104 14007-14081/com.example.wrd I/ProviderInstaller: Installed default security provider GmsCore_OpenSSL
10-09 12:51:31.114 14007-14007/com.example.wrd D/AndroidRuntime: Shutting down VM
10-09 12:51:31.114 14007-14007/com.example.wrd E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.wrd, PID: 14007
java.lang.RuntimeException: Unable to instantiate service com.example.wrd.ble.BLE_Service: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3841)
at android.app.ActivityThread.access$2100(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
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)
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3838)
at android.app.ActivityThread.access$2100(ActivityThread.java:229) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:7325) 
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) 
My service looks like this:
public class BLE_Service extends Service {
private Home ma;
private boolean mscanning;
public boolean Read = false;
private Handler mHandler;
private long scanPeriod;
private int signalStrength;
//Intent string
private static String DeviceAddress;
private static final String TAG = "BLE_Service";
// Bluetooth objects that we need to interact with
private static BluetoothManager mBluetoothManager;
private static BluetoothAdapter mBluetoothAdapter;
private static BluetoothGatt mBluetoothGatt;
private static BluetoothDevice device;
private static BluetoothGattCharacteristic BLECharacterisitc;
private final static String BaseUuid = "00000000-0000-1000-8000-00805f9b34f";
private final static String CSUuid = "00002902-0000-1000-8000-00805f9b34fb";
private final static String UuidWrite = BaseUuid + "0";
private final static String UuidRead = BaseUuid + "1";
private final static String UuidRead2 = BaseUuid + "2";
private final static String state_RW = BaseUuid + "0";
private final static String treatmentSettings_RW = BaseUuid + "1";
private final static String adjustment_RW = BaseUuid + "2";
private final static String validation_R = BaseUuid + "3";
//Broadcasts
public final static String BROADCAST_ADDED = "added";
public final static String BROADCAST_ADDEDFrag = "added";
// Bluetooth characteristics that we need to read/write
private static BluetoothGattCharacteristic mCharacterisitc, mCharacterisitc2, mCharacterisitcWrite, mCharacterisitc_state_RW,
mCharacterisitc_treatmentSettings_RW, mCharacterisitc_adjustment_RW, mCharacterisitc_validation_R;
private static StringBuilder sb = new StringBuilder();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean connecting(String DeviceAddress) {
Log.d(TAG, "Connection State: connect");
device = mBluetoothAdapter.getRemoteDevice(DeviceAddress);
if (device == null) {
Log.d(TAG, "Connection State Device Not Available ");
return false;
} else {
Log.d(TAG, "Connection State Connecting...");
device.connectGatt(this, false, mGattCallback);
return true;
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean disconnect() {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
return true;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void checkConnectedDevices() {
if (mBluetoothGatt != null){
String DeviceString = mBluetoothGatt.getDevice().getAddress();
String NameString = mBluetoothGatt.getDevice().getName();
Log.d(TAG, "checkConnectedDevices: " + NameString);
//broadCastHEX(BROADCAST_ADDEDFrag, NameString+";"+DeviceString, "get_conn_BLE_return");
}else{
//broadCastHEX(BROADCAST_ADDEDFrag, null, "Connected_BLE_Devices_return");
}
}
public class LocalBinder extends Binder {
public BLE_Service getService() {
return BLE_Service.this;
}
}
private final IBinder mBinder = new LocalBinder();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
/**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean initialize() {
Log.d(TAG, "mBluetoothManager: service");
// 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;
}
}
Log.d(TAG, "mBluetoothManager: initialize");
BluetoothManager bluetoothManager = (BluetoothManager) getBaseContext().getSystemService(Context.BLUETOOTH_SERVICE);
List<BluetoothDevice> devices = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
Log.d(TAG, "mBluetoothManager: initialize device" + devices.toString());
for(BluetoothDevice device : devices) {
if(device.getType() == BluetoothDevice.DEVICE_TYPE_LE) {
Log.d(TAG, "mBluetoothManager: running loop" + device.getName() + "\n");
}else{
Log.d(TAG, "mBluetoothManager: nothing" + device.getName() + "\n");
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public BLE_Service(Home home, long scanPeriod, int signalStrength) {
ma = home;
mHandler = new Handler();
this.scanPeriod = scanPeriod;
this.signalStrength = signalStrength;
final BluetoothManager bluetoothManager =
(BluetoothManager) ma.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
public boolean isScanning() {
return mscanning;
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void start() {
if (!Utils.checkBluetooth(mBluetoothAdapter)) {
Utils.requestUserBluetooth(ma);
ma.stopScan();
} else {
scanLeDevice(true);
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void stop() {
scanLeDevice(false);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void scanLeDevice(final boolean enable) {
if (enable && !mscanning) {
Utils.toast(ma.getApplication(), "Starting BLE Scan...");
mHandler.postDelayed(new Runnable() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void run() {
Utils.toast(ma.getApplicationContext(), "Stopping BLE scan...");
mscanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
ma.stopScan();
}
}, scanPeriod);
mscanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
Log.d(TAG, "Connection State Change: " + status + " -> " + connectionState(newState));
gatt.discoverServices();
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
/*
* Once successfully connected, we must next discover all the services on the
* device before we can read and write their characteristics.
*/
mBluetoothGatt = gatt;
BluetoothDevice device = gatt.getDevice();
Log.d(TAG, "Connection State onConnectionStateChange: " + device);
} else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
/*
* If at any point we disconnect, send a message to clear the weather values
* out of the UI
*/
Log.d(TAG, "Connection State: 2");
} else if (status != BluetoothGatt.GATT_SUCCESS) {
/*
* If there is a failure at any stage, simply disconnect
*/
}
}
/**
* This is called when a service discovery has completed.
*
* It gets the characteristics we are interested in and then
* broadcasts an update to the main activity.
*
* @param gatt The GATT database object
* @param status Status of whether the write was successful.
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onServicesDiscovered(final BluetoothGatt gatt, int status) {//prøv med ekstra status på denne
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService mBluetoothGattService = gatt.getService(UUID.fromString(CSUuid));
if (mBluetoothGattService != null) {
Log.i(TAG, "Connection State: Service characteristic UUID found: " + mBluetoothGattService.getUuid().toString());
mCharacterisitc = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidRead));
mCharacterisitc2 = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidRead2));
mCharacterisitcWrite = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidWrite));
//First activate buttons here....
Log.w(TAG, "Connection State 1: mCharacterisitc " + mCharacterisitc + " " + mCharacterisitc2);
Intent broadcastIntent = new Intent().putExtra("ConnState", true);
broadcastIntent.setAction(BLE_Service.BROADCAST_ADDED);
LocalBroadcastManager.getInstance(BLE_Service.this).sendBroadcast(broadcastIntent);
if(Read){
readCharacteristic(gatt, mCharacterisitc);
}
} else {
Log.i(TAG, "Connection State: Service characteristic not found for UUID: " + UuidRead);
}
}
}
private String connectionState(int status) {
switch (status) {
case BluetoothProfile.STATE_CONNECTED:
return "Connection State: Connected";
case BluetoothProfile.STATE_DISCONNECTED:
return "Connection State: Disconnected";
case BluetoothProfile.STATE_CONNECTING:
return "Connection State: Connecting";
case BluetoothProfile.STATE_DISCONNECTING:
return "Connection State: Disconnecting";
default:
return String.valueOf(status);
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "Connection State: onCharacteristicRead");
Log.w(TAG, "Connection State: Read 1");
// Verify that the read was the LED state
String uuid = characteristic.getUuid().toString();
// In this case, the only read the app does is the LED state.
// If the application had additional characteristics to read we could
// use a switch statement here to operate on each one separately.
if (uuid.equalsIgnoreCase(UuidRead)) {
Log.w(TAG, "Connection State: Read 2");
final int Val = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
broadCast(BROADCAST_ADDEDFrag, Val, "read_Service");
Log.i(TAG, "Connection State: onCharacteristicRead: " + Val);
Log.d(TAG, "Connection State Read state: "+Read);
readCharacteristic(gatt, mCharacterisitc2);
}
if (uuid.equalsIgnoreCase(UuidRead2)) {
Log.w(TAG, "Connection State: Read 3");
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));
String msg = "letter: " + new String(data) + "\nHEX: " + stringBuilder.toString();
Log.d(TAG, "Connection State: onCharacteristicRead2: 4 " + msg);
broadCastHEX(BROADCAST_ADDEDFrag, msg, "read_Service2");
}
Read = false; //Has to be set to false in the last read message..
Log.d(TAG, "Connection State Read state: "+Read);
}
}
}
};
/**
* Runs service discovery on the connected device.
*
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void discoverServices() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "Connection State BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.discoverServices();
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void Write(Integer integer) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "Connection State BluetoothAdapter not initialized");
return;
}
Integer Val = integer;
byte[] byteVal;
byteVal = intToByteArray(Val);
mCharacterisitcWrite.setValue(byteVal);
Log.d(TAG, "Connection State write 1: " + byteVal);
mBluetoothGatt.writeCharacteristic(mCharacterisitcWrite);
}
public static byte[] intToByteArray(int a) {
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
/**
* This method is used to read the state of the LED from the device
*/
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void readCharacteristic(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || gatt == null) {
Log.w(TAG, "Connection State: BluetoothAdapter not initialized 2");
return;
}
Log.w(TAG, "Connection State: BluetoothAdapter initialized");
gatt.readCharacteristic(characteristic);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final int new_rssi = rssi;
if (rssi > signalStrength && device.getName() != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
try {
FragmentBLE.addDevice(device, new_rssi);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
};
public void broadCast(String broadcastTXT, Integer Val, String key) {
Log.d(TAG, "Connection State: -> broadCast: Service Broadcast");
Intent broadcastIntent = new Intent().putExtra(key, Val);
broadcastIntent.setAction(broadcastTXT);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
public void broadCastHEX(String broadcastTXT, String Val, String key) {
Log.d(TAG, "Connection State: -> broadCast: Service Broadcast");
Intent broadcastIntent = new Intent().putExtra(key, Val);
broadcastIntent.setAction(broadcastTXT);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
}
So what causes this error to occure?
looks like it's somthing to do with java.lang.RuntimeException: Unable to instantiate service com.example.wrd.ble.BLE_Service
, and I've been serching on it, but can't seem to find anything that helps.
EDIT
So my filled contructer is done before my empty contructer is set. I bind in my onStart()
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
protected void onStart() {
super.onStart();
// Start the BLE Service
Log.d(TAG, "Starting BLE Service");
Intent gattServiceIntent = new Intent(this, BLE_Service.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Log.d(TAG, "Bluetooth is Enabled");
registerReceiver(mBTStateUpdateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
And then in my oncreate I run the following
mBTLeScanner = new BLE_Service(this, 7500, -75);
but somehow BLE_Service(this, 7500, -75)
is finished before onStart()
答案1
得分: 2
创建一个空的构造函数。
BLE_Service(){
}
英文:
Create an empty constructor.
BLE_Service(){
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论