英文:
(Android java) Sending notification to calendar failed
问题
我正在编写一个应用程序,其中有一个按钮,点击该按钮会发送一个包含在通知中的文本到Google日历,然后用户的手机日历将从Google日历接收通知。
奇怪的是,我的代码在三星Note 8上完美运行,但在三星Note 4上失败。如何使这段代码在Note 8和Note 4上工作(或最好是在早期设备上工作)?
值得注意的是,我确保了这台Note 4设备已连接到Google日历帐户,因此它应该能够从Google日历接收通知。
这是我尝试的代码。在按下按钮后,会触发以下辅助方法:
public void setPreDefinedNotificationFor1Hour() {
// 设置通知
ContentResolver cr = getContentResolver();
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.DTSTART, System.currentTimeMillis() + 60 * 60 * 1000); // 1小时后开始
event.put(CalendarContract.Events.DTEND, System.currentTimeMillis() + 60 * 60 * 1000 + 60 * 60 * 1000);
event.put(CalendarContract.Events.TITLE, getResources().getString(R.string.Do_you_remember_this_word) + selectedListviewItemValue);
event.put(CalendarContract.Events.DESCRIPTION, getResources().getString(R.string.app_name));
event.put(CalendarContract.Events.ALL_DAY, false);
event.put(CalendarContract.Events.CALENDAR_ID, 3);
event.put(CalendarContract.Events.EVENT_TIMEZONE, Calendar.getInstance().getTimeZone().getID());
Uri newEvent = cr.insert(CalendarContract.Events.CONTENT_URI, event);
assert newEvent != null;
long eventID = Long.parseLong(Objects.requireNonNull(newEvent.getLastPathSegment())); // 获取Uri中的最后一个元素,即事件ID
ContentValues reminder = new ContentValues();
reminder.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(newEvent));
reminder.put(CalendarContract.Reminders.MINUTES, 0);
reminder.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
Uri newReminder = cr.insert(CalendarContract.Reminders.CONTENT_URI, reminder);
}
我在清单文件中请求了权限,如下所示:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<permission android:name="android.permission.READ_CALENDAR" />
<permission android:name="android.permission.WRITE_CALENDAR" />
我已经以编程方式请求了权限,如下所示:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == WRITE_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(LOG_TAG, "Write Permission Failed");
Toast.makeText(this, getString(R.string.External_storage_permission), Toast.LENGTH_LONG).show();
finish();
}
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void requestWritePermission() {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_PERMISSION);
}
}
这是有关某些SQLiteException的错误日志:
05-03 15:26:43.177 9346-9346/com.example.android.dictionaryalmighty2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.dictionaryalmighty2, PID: 9346
android.database.sqlite.SQLiteException: null
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:179)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:1284)
at com.example.android.dictionaryalmighty2.UserInputHistory.i(:959)
at c.e.a.a.l3.onClick(:428)
...
这是有关约束违规的另一个错误报告:
05-03 15:25:56.157 5392-20740/? E/SQLiteDatabase: Error inserting service_kind=0 source=16 tag=Measurement.PackageMeasurementTaskService.UPLOAD_TASK_TAG requires_charging=0 target_package=com.google.android.gms source_version=201515000 required_network_type=0 flex_time=2672000 target_class=com.google.android.gms.measurement.PackageMeasurementTaskService runtime=1588490756157 retry_strategy={"maximum_backoff_seconds":{"3600":0},"initial_backoff_seconds":{"30":0},"retry_policy":{"0":0}} preferred_network_type=1 required_idleness_state=0 preferred_charging_state=1 last_runtime=0 period=5346000 task_type=0 job_id=-1 user_id=0
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: pending_ops.tag, pending_ops.target_class, pending_ops.target_package, pending_ops.user_id (code 2067)
...
更新:这是我正在使用的依赖项:
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.19'
implementation 'com.github.yalantis:ucrop:2.2.3'
implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'com.jakewharton:process-phoenix:2.0.0'
implementation 'com.github.sachinvarma:EasyPermission:1.0.1'
implementation 'com.github.fibelatti:MaterialShowcaseView:2.1.0'
implementation 'com.daimajia.easing:library:2.0@aar'
implementation 'com.daimajia.androidanimations:library:2.3@aar'
implementation 'com.crowdfire.cfalertdialog:cfalertdialog:1.1.0'
implementation 'com.teprinciple:updateapputils:2.3.0'
implementation 'com.google.android.gms:
<details>
<summary>英文:</summary>
I'm writing an app that has a button to send a text wrapped in a notification to google calendar and then the user's phone calendar will receive the notification from google calendar.
The strange thing is that my code works perfectly on Samsung Note 8 but fails on Samsung Note 4. How do I make this code to work on Note 8 and Note 4 (or preferrably on previous devices)?
For the record, I've made sure this Note 4 device is connected to the google calendar account so it should be able to receive notifications from google calendar.
**This is the code I tried. On button pressed, the following helper method is triggered.**
Note: Logcat reports the app stops at this line "Uri newReminder = cr.insert(CalendarContract.Reminders.CONTENT_URI, reminder)". Android Studio says variable "newReminder" is never used.
public void setPreDefinedNotificationFor1Hour() {
//Set notification
ContentResolver cr = getContentResolver();
ContentValues event = new ContentValues();
event.put(CalendarContract.Events.DTSTART, System.currentTimeMillis()+ 60*60*1000); //Start in 1 hour
event.put(CalendarContract.Events.DTEND, System.currentTimeMillis()+60*60*1000+60*60*1000);
event.put(CalendarContract.Events.TITLE, getResources().getString(R.string.Do_you_remember_this_word) + selectedListviewItemValue);
event.put(CalendarContract.Events.DESCRIPTION, getResources().getString(R.string.app_name));
event.put(CalendarContract.Events.ALL_DAY, false);
event.put(CalendarContract.Events.CALENDAR_ID, 3);
event.put(CalendarContract.Events.EVENT_TIMEZONE, Calendar.getInstance().getTimeZone().getID());
Uri newEvent = cr.insert(CalendarContract.Events.CONTENT_URI, event);
assert newEvent != null;
long eventID = Long.parseLong(Objects.requireNonNull(newEvent.getLastPathSegment())); // get the event ID that is the last element in the Uri
ContentValues reminder = new ContentValues();
reminder.put(CalendarContract.Reminders.EVENT_ID, ContentUris.parseId(newEvent));
reminder.put(CalendarContract.Reminders.MINUTES, 0);
reminder.put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT);
Uri newReminder = cr.insert(CalendarContract.Reminders.CONTENT_URI, reminder);
}
I have requested permission in Manifest like so:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<permission android:name="android.permission.READ_CALENDAR" />
<permission android:name="android.permission.WRITE_CALENDAR" />
I've requested permission programically like so:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if(requestCode == WRITE_PERMISSION){
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(LOG_TAG, "Write Permission Failed");
Toast.makeText(this,getString(R.string.External_storage_permission), Toast.LENGTH_LONG).show();
finish();
}
}
}
@RequiresApi(api = Build.VERSION_CODES.M) //This RequiresApi line has to be here or else this chunk of code will fail on Samsung Note 8
private void requestWritePermission(){
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},WRITE_PERMISSION);
}
}
Here is the error log regarding some SQLiteException:
05-03 15:26:43.177 9346-9346/com.example.android.dictionaryalmighty2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.dictionaryalmighty2, PID: 9346
android.database.sqlite.SQLiteException: null
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:179)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
at android.content.ContentResolver.insert(ContentResolver.java:1284)
at com.example.android.dictionaryalmighty2.UserInputHistory.i(:959)
at c.e.a.a.l3.onClick(:428)
at c.c.a.a$i.onCheckedChanged(:694)
at android.widget.CompoundButton.setChecked(CompoundButton.java:165)
at android.widget.CompoundButton.toggle(CompoundButton.java:118)
at android.widget.RadioButton.toggle(RadioButton.java:76)
at android.widget.CompoundButton.performClick(CompoundButton.java:123)
at android.view.View$PerformClick.run(View.java:22546)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7225)
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)
05-03 15:26:43.202 3964-9593/? E/android.os.Debug: ro.product_ship = true
05-03 15:26:43.202 3964-9593/? E/android.os.Debug: ro.debug_level = 0x4f4c
05-03 15:26:43.202 3964-9593/? E/android.os.Debug: sys.mobilecare.preload = false
05-03 15:26:43.807 13300-13300/? E/daemonapp: [MSC_Daemon]>>> WU:512 [0:0] [NameNotFoundException] sandPakage !!!!!
05-03 15:26:43.812 13300-13300/? E/daemonapp: [MSC_Daemon]>>> WU:512 [0:0] [NameNotFoundException] sandPakage !!!!!
05-03 15:26:44.132 9605-9605/? E/Zygote: v2
05-03 15:26:44.132 9605-9605/? E/Zygote: accessInfo : 0
05-03 15:26:44.392 9624-9624/? E/Zygote: v2
05-03 15:26:44.392 9624-9624/? E/Zygote: accessInfo : 0
05-03 15:26:44.537 9605-9605/? E/LWLocationManager: findLocationType() : cursor_location.moveToFirst() return false!!
05-03 15:26:45.372 9641-9641/? E/Zygote: v2
05-03 15:26:45.372 9641-9641/? E/Zygote: accessInfo : 0
05-03 15:26:45.482 9641-9641/? E/ActivityThread: Failed to find provider info for com.tencent.mm.coolassist.debugprovider
05-03 15:26:46.092 5639-5702/? E/ContactsProvider_EventLog: Flush buffer to file cnt : 2 size : 0Kb duration : 1ms lastUpdatedAfter : 19642 ms mFlush_time_threasold : 2000 mCurrentSize : 410
05-03 15:26:49.057 3964-5789/? E/Watchdog: !@Sync 1123 [05-03 15:26:49.062]
05-03 15:26:50.132 5639-5702/? E/ContactsProvider_EventLog: Flush buffer to file cnt : 2 size : 2Kb duration : 16ms lastUpdatedAfter : 4040 ms mFlush_time_threasold : 2000 mCurrentSize : 1366
05-03 15:26:51.577 3964-4185/? E/ViewRootImpl: sendUserActionEvent() mView == null
05-03 15:26:51.702 3964-5138/? E/ConnectivityService: RemoteException caught trying to send a callback msg for NetworkRequest [ id=326, legacyType=-1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED] ]
05-03 15:26:51.702 3964-5138/? E/ConnectivityService: RemoteException caught trying to send a callback msg for NetworkRequest [ id=327, legacyType=-1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED] ]
05-03 15:26:51.732 9712-9712/? E/Zygote: v2
05-03 15:26:51.737 9712-9712/? E/Zygote: accessInfo : 0
This is another error report regarding constraint violation:
05-03 15:25:56.157 5392-20740/? E/SQLiteDatabase: Error inserting service_kind=0 source=16 tag=Measurement.PackageMeasurementTaskService.UPLOAD_TASK_TAG requires_charging=0 target_package=com.google.android.gms source_version=201515000 required_network_type=0 flex_time=2672000 target_class=com.google.android.gms.measurement.PackageMeasurementTaskService runtime=1588490756157 retry_strategy={"maximum_backoff_seconds":{"3600":0},"initial_backoff_seconds":{"30":0},"retry_policy":{"0":0}} preferred_network_type=1 required_idleness_state=0 preferred_charging_state=1 last_runtime=0 period=5346000 task_type=0 job_id=-1 user_id=0
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: pending_ops.tag, pending_ops.target_class, pending_ops.target_package, pending_ops.user_id (code 2067)
#################################################################
Error Code : 2067 (SQLITE_CONSTRAINT_UNIQUE)
Caused By : Abort due to constraint violation.
(UNIQUE constraint failed: pending_ops.tag, pending_ops.target_class, pending_ops.target_package, pending_ops.user_id (code 2067))
#################################################################
at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:919)
at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1609)
at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1479)
at apnp.a(:com.google.android.gms@201515015@20.15.15 (040300-306758586):76)
at apne.a(:com.google.android.gms@201515015@20.15.15 (040300-306758586):173)
at apne.a(:com.google.android.gms@201515015@20.15.15 (040300-306758586):21)
at apne.a(:com.google.android.gms@201515015@20.15.15 (040300-306758586):167)
at apjn.run(:com.google.android.gms@201515015@20.15.15 (040300-306758586):8)
at ssd.b(:com.google.android.gms@201515015@20.15.15 (040300-306758586):12)
at ssd.run(:com.google.android.gms@201515015@20.15.15 (040300-306758586):7)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at sye.run(:com.google.android.gms@201515015@20.15.15 (040300-306758586):0)
at java.lang.Thread.run(Thread.java:818)
**Update: Here are the dependencies I'm using**
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
android {
//Upper part omitted for privacy
compileSdkVersion 29
defaultConfig {
//applicationId omitted for privacy
minSdkVersion 21
targetSdkVersion 29
versionCode 9
versionName "1.0.8"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
signingConfig signingConfigs.release
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug{
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.19'
implementation 'com.github.yalantis:ucrop:2.2.3'
implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'com.jakewharton:process-phoenix:2.0.0'
implementation 'com.github.sachinvarma:EasyPermission:1.0.1'
implementation 'com.github.fibelatti:MaterialShowcaseView:2.1.0'
// implementation 'com.android.support:support-compat:28.0.0' This line is commented out because it clashes with targetSdkVersion 29 and I've already migrated to Android X.
implementation 'com.daimajia.easing:library:2.0@aar'
implementation 'com.daimajia.androidanimations:library:2.3@aar'
implementation 'com.crowdfire.cfalertdialog:cfalertdialog:1.1.0'
implementation 'com.teprinciple:updateapputils:2.3.0'
implementation 'com.google.android.gms:play-services-vision:20.0.0'
implementation 'com.google.android.gms:play-services-auth:18.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.work:work-runtime:2.3.4'
implementation 'com.google.firebase:firebase-database:19.3.0'
implementation 'com.firebaseui:firebase-ui-database:0.4.4'
implementation 'com.google.firebase:firebase-messaging:20.2.0'
implementation 'com.google.firebase:firebase-dynamic-links:19.1.0'
implementation 'com.google.firebase:firebase-storage:19.1.1'
implementation 'com.google.firebase:firebase-config:19.1.4'
implementation 'com.google.firebase:firebase-analytics:17.4.2'
implementation 'com.google.firebase:firebase-auth:19.3.1'
implementation 'com.firebaseui:firebase-ui-auth:4.3.1'
implementation 'com.facebook.android:facebook-android-sdk:6.0.0'
}
</details>
专注分享java语言的经验与见解,让所有开发者获益!
评论