预期 BEGIN_OBJECT 但在第 1 行第 14 列路径 $ 与对象和 SQLite 中为 NUMBER
Expected BEGIN_OBJECT but was NUMBER at line 1 column 14 path $ with Object and SQLite
我正在尝试将 Android 通知对象存储在 SQLite 数据库中,但出现错误。
首先,在我解释错误之前,让我解释一下什么是有效的。我有一个 NotificationListenerService class 用于侦听通知并阻止它们出现。您可以在下面的 class 中看到这一点。当通知被阻止时,我想将它们存储在 SQLite 数据库中。但是,我的问题是如何将 Notification 对象存储在数据库中,所以我将 GSON 转到 JSON 路由。因此,无论何时销毁通知,它都会将 Notification 对象转换为 Json 并将其存储在数据库中(连同其他一些东西)。
NotificationListenerService:
public class NotificationListenerServiceUsage extends NotificationListenerService {
private static final String TAG = "NotificationListenerSer";
@Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
@Override
public void onNotificationPosted(StatusBarNotification sbn){
cancelAllNotifications();
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn){
// 1. Getting DB Context and initializing SQLiteDatabase
Context context = getApplicationContext();
SQLiteDatabase sqLiteDatabase = context.openOrCreateDatabase("notifications", Context.MODE_PRIVATE,null);
// 2. Initialize the DBHelper class.
DBHelper dbHelper = new DBHelper(sqLiteDatabase);
// 3. Getting the content for the DB
String notificationKey = sbn.getKey();
Integer notificationID = sbn.getId();
long postTime = sbn.getPostTime();
Notification notificationContent = sbn.getNotification();
// 3.1 Converting the Notification Object into a String
Gson gson = new Gson();
String notificationInput = gson.toJson(notificationContent);
// 4. Saving into the DB
dbHelper.saveNotifications(notificationKey, notificationID, postTime, notificationInput);
// FOR TESTING PURPOSES
Notification finalNotificationObj = gson.fromJson(notificationInput, Notification.class);
// FOR TESTING PURPOSES
Log.d(TAG, "onNotificationRemoved: " + "INPUT: " + notificationContent);
Log.d(TAG, "onNotificationRemoved: " + "JSON: " + notificationInput);
Log.d(TAG, "onNotificationRemoved: " + "OUTPUT: " + finalNotificationObj );
}
}
渲染的结果 Json 如下:
{
"audioAttributes":{
"mContentType":4,
"mFlags":2048,
"mFormattedTags":"",
"mSource":-1,
"mUsage":5
},
"audioStreamType":-1,
"color":0,
"defaults":0,
"extras":{
"mParcelledData":{
"mNativePtr":3569564416
}
},
"flags":0,
"icon":2131230820,
"iconLevel":0,
"ledARGB":0,
"ledOffMS":0,
"ledOnMS":0,
"mChannelId":"channel1",
"mSmallIcon":{
"mString1":"com.example.finalproject",
"mType":2
},
"number":0,
"priority":1,
"visibility":0,
"when":1587406911152
}
所以问题是什么?
我能够成功地将字符串 Json 存储在数据库中,但是当我将它从数据库中拉回并尝试将其转换回 Notification 对象时,我得到了一个 IllegalStateException。堆栈跟踪在下面供参考。我感觉在存储字符串 Json 并将其拉回时出现问题,因为在上面的 Notificaiton Listener 文件中,我只记录了一些内容并且转换为 Json 并返回成功并且完全匹配。下面是我正在使用的数据库助手 class,它显示了如何存储和提取内容。问题中的错误出现在readNotifications()方法中。
关于为什么会出现此错误有任何想法吗?
数据库访问Class:
public class DBHelper {
SQLiteDatabase sqLiteDatabase;
private static final String TAG = "DBHelper";
public DBHelper(SQLiteDatabase sqLiteDatabase) {
this.sqLiteDatabase = sqLiteDatabase;
}
public void createTable (){
sqLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS notifications" + "(notificationKey TEXT, notificationID INTEGER, postTime BIGINT, notificatoinContent TEXT)");
}
public ArrayList<NotificationObject> readNotifications(){
// 1. Checking the table and creating a NotificationObject instance
createTable();
ArrayList<NotificationObject> notificationObjects = new ArrayList<>();
// 2. Starting the cursor at the top of the notification Table
Cursor c = sqLiteDatabase.rawQuery(("SELECT * from notifications"), null);
// 3. Gets the index of all of the columns so that the cursor can reference it from the row
int keyIndex = c.getColumnIndex("notificationKey");
int notificationIDIndex = c.getColumnIndex("notificationID");
int postTimeIndex = c.getColumnIndex("postTime");
int notificationContentIndex = c.getColumnIndex("postTime");
// 4. Moves the cursor to the top
c.moveToFirst();
// 5. While loop to loop through all the rows
while (!c.isAfterLast()){
// 5.1 Getting all of the values from row of the cursor
String notificationKey = c.getString(keyIndex);
Integer notificationID = c.getInt(notificationIDIndex);
long postTime = c.getLong(postTimeIndex);
String notificationContent = c.getString(notificationContentIndex);
// 5.2 Converting Notification content back to Notification Object
Gson gson = new Gson();
Notification finalNotificationObj = gson.fromJson(notificationContent, Notification.class);
// 5.3 Adds all of the content to the NotificationObject Object
NotificationObject notificationObject = new NotificationObject(notificationKey, notificationID, postTime, finalNotificationObj);
// 5.4 Adds the notificationObject to the arraylist
notificationObjects.add(notificationObject);
c.moveToNext();
}
c.close();
sqLiteDatabase.close();
return notificationObjects;
}
public void saveNotifications (String notificationKey, Integer notificationID, long postTime, String notificationContent){
createTable();
sqLiteDatabase.execSQL(String.format("INSERT INTO notifications (notificationKey, notificationID, postTime, notificatoinContent)" +
" VALUES ('%s', '%s', '%s', '%s')", notificationKey, notificationID, postTime, notificationContent));
}
}
堆栈跟踪:
2020-04-20 13:55:52.881 12060-12060/com.example.finalproject E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.finalproject, PID: 12060
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 14 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
at com.example.finalproject.BatchNotifications.DBHelper.readNotifications(DBHelper.java:54)
at com.example.finalproject.BatchNotifications.Batch_Notifications.getHeldNotifications(Batch_Notifications.java:290)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 14 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:386)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
at com.example.finalproject.BatchNotifications.DBHelper.readNotifications(DBHelper.java:54)
at com.example.finalproject.BatchNotifications.Batch_Notifications.getHeldNotifications(Batch_Notifications.java:290)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
答案在上面发布的数据库助手 class 中。在 readNotifications 方法的第 3 步中,行
int notificationContentIndex = c.getColumnIndex("postTime");
指向了错误的列。它指向返回 int 值而不是 JSON 字符串的 postTime 列。将该 int 传递给 GSON / JSON 转换器导致上述错误。将其指向正确的列解决了问题。
我正在尝试将 Android 通知对象存储在 SQLite 数据库中,但出现错误。
首先,在我解释错误之前,让我解释一下什么是有效的。我有一个 NotificationListenerService class 用于侦听通知并阻止它们出现。您可以在下面的 class 中看到这一点。当通知被阻止时,我想将它们存储在 SQLite 数据库中。但是,我的问题是如何将 Notification 对象存储在数据库中,所以我将 GSON 转到 JSON 路由。因此,无论何时销毁通知,它都会将 Notification 对象转换为 Json 并将其存储在数据库中(连同其他一些东西)。
NotificationListenerService:
public class NotificationListenerServiceUsage extends NotificationListenerService {
private static final String TAG = "NotificationListenerSer";
@Override
public IBinder onBind(Intent intent) {
return super.onBind(intent);
}
@Override
public void onNotificationPosted(StatusBarNotification sbn){
cancelAllNotifications();
}
@Override
public void onNotificationRemoved(StatusBarNotification sbn){
// 1. Getting DB Context and initializing SQLiteDatabase
Context context = getApplicationContext();
SQLiteDatabase sqLiteDatabase = context.openOrCreateDatabase("notifications", Context.MODE_PRIVATE,null);
// 2. Initialize the DBHelper class.
DBHelper dbHelper = new DBHelper(sqLiteDatabase);
// 3. Getting the content for the DB
String notificationKey = sbn.getKey();
Integer notificationID = sbn.getId();
long postTime = sbn.getPostTime();
Notification notificationContent = sbn.getNotification();
// 3.1 Converting the Notification Object into a String
Gson gson = new Gson();
String notificationInput = gson.toJson(notificationContent);
// 4. Saving into the DB
dbHelper.saveNotifications(notificationKey, notificationID, postTime, notificationInput);
// FOR TESTING PURPOSES
Notification finalNotificationObj = gson.fromJson(notificationInput, Notification.class);
// FOR TESTING PURPOSES
Log.d(TAG, "onNotificationRemoved: " + "INPUT: " + notificationContent);
Log.d(TAG, "onNotificationRemoved: " + "JSON: " + notificationInput);
Log.d(TAG, "onNotificationRemoved: " + "OUTPUT: " + finalNotificationObj );
}
}
渲染的结果 Json 如下:
{
"audioAttributes":{
"mContentType":4,
"mFlags":2048,
"mFormattedTags":"",
"mSource":-1,
"mUsage":5
},
"audioStreamType":-1,
"color":0,
"defaults":0,
"extras":{
"mParcelledData":{
"mNativePtr":3569564416
}
},
"flags":0,
"icon":2131230820,
"iconLevel":0,
"ledARGB":0,
"ledOffMS":0,
"ledOnMS":0,
"mChannelId":"channel1",
"mSmallIcon":{
"mString1":"com.example.finalproject",
"mType":2
},
"number":0,
"priority":1,
"visibility":0,
"when":1587406911152
}
所以问题是什么?
我能够成功地将字符串 Json 存储在数据库中,但是当我将它从数据库中拉回并尝试将其转换回 Notification 对象时,我得到了一个 IllegalStateException。堆栈跟踪在下面供参考。我感觉在存储字符串 Json 并将其拉回时出现问题,因为在上面的 Notificaiton Listener 文件中,我只记录了一些内容并且转换为 Json 并返回成功并且完全匹配。下面是我正在使用的数据库助手 class,它显示了如何存储和提取内容。问题中的错误出现在readNotifications()方法中。
关于为什么会出现此错误有任何想法吗?
数据库访问Class:
public class DBHelper {
SQLiteDatabase sqLiteDatabase;
private static final String TAG = "DBHelper";
public DBHelper(SQLiteDatabase sqLiteDatabase) {
this.sqLiteDatabase = sqLiteDatabase;
}
public void createTable (){
sqLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS notifications" + "(notificationKey TEXT, notificationID INTEGER, postTime BIGINT, notificatoinContent TEXT)");
}
public ArrayList<NotificationObject> readNotifications(){
// 1. Checking the table and creating a NotificationObject instance
createTable();
ArrayList<NotificationObject> notificationObjects = new ArrayList<>();
// 2. Starting the cursor at the top of the notification Table
Cursor c = sqLiteDatabase.rawQuery(("SELECT * from notifications"), null);
// 3. Gets the index of all of the columns so that the cursor can reference it from the row
int keyIndex = c.getColumnIndex("notificationKey");
int notificationIDIndex = c.getColumnIndex("notificationID");
int postTimeIndex = c.getColumnIndex("postTime");
int notificationContentIndex = c.getColumnIndex("postTime");
// 4. Moves the cursor to the top
c.moveToFirst();
// 5. While loop to loop through all the rows
while (!c.isAfterLast()){
// 5.1 Getting all of the values from row of the cursor
String notificationKey = c.getString(keyIndex);
Integer notificationID = c.getInt(notificationIDIndex);
long postTime = c.getLong(postTimeIndex);
String notificationContent = c.getString(notificationContentIndex);
// 5.2 Converting Notification content back to Notification Object
Gson gson = new Gson();
Notification finalNotificationObj = gson.fromJson(notificationContent, Notification.class);
// 5.3 Adds all of the content to the NotificationObject Object
NotificationObject notificationObject = new NotificationObject(notificationKey, notificationID, postTime, finalNotificationObj);
// 5.4 Adds the notificationObject to the arraylist
notificationObjects.add(notificationObject);
c.moveToNext();
}
c.close();
sqLiteDatabase.close();
return notificationObjects;
}
public void saveNotifications (String notificationKey, Integer notificationID, long postTime, String notificationContent){
createTable();
sqLiteDatabase.execSQL(String.format("INSERT INTO notifications (notificationKey, notificationID, postTime, notificatoinContent)" +
" VALUES ('%s', '%s', '%s', '%s')", notificationKey, notificationID, postTime, notificationContent));
}
}
堆栈跟踪:
2020-04-20 13:55:52.881 12060-12060/com.example.finalproject E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.finalproject, PID: 12060
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 14 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
at com.example.finalproject.BatchNotifications.DBHelper.readNotifications(DBHelper.java:54)
at com.example.finalproject.BatchNotifications.Batch_Notifications.getHeldNotifications(Batch_Notifications.java:290)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 14 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:386)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215)
at com.google.gson.Gson.fromJson(Gson.java:932)
at com.google.gson.Gson.fromJson(Gson.java:897)
at com.google.gson.Gson.fromJson(Gson.java:846)
at com.google.gson.Gson.fromJson(Gson.java:817)
at com.example.finalproject.BatchNotifications.DBHelper.readNotifications(DBHelper.java:54)
at com.example.finalproject.BatchNotifications.Batch_Notifications.getHeldNotifications(Batch_Notifications.java:290)
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access00(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
答案在上面发布的数据库助手 class 中。在 readNotifications 方法的第 3 步中,行
int notificationContentIndex = c.getColumnIndex("postTime");
指向了错误的列。它指向返回 int 值而不是 JSON 字符串的 postTime 列。将该 int 传递给 GSON / JSON 转换器导致上述错误。将其指向正确的列解决了问题。