Quellcode durchsuchen

local notification

leon vor 1 Jahr
Ursprung
Commit
a32a231e55

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
android/app/src/main/assets/index.android.bundle


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
android/app/src/main/assets/index.android.map


+ 36 - 15
android/app/src/main/java/com/hola/AlarmReceiver.java

@@ -1,36 +1,57 @@
 package com.hola;
 
-import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.graphics.BitmapFactory;
 import android.widget.Toast;
 
 import androidx.core.app.NotificationCompat;
+import androidx.core.app.NotificationManagerCompat;
 
 import java.time.Duration;
 
 public class AlarmReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
-        // 获取通知的相关数据
-        String title = intent.getStringExtra("title");
-        String message = intent.getStringExtra("message");
 
-        // 创建并显示通知
-        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "my_channel_id")
-                .setSmallIcon(R.drawable.picture_ic_flash_on)
-                .setContentTitle(title)
-                .setContentText(message)
-                .setPriority(NotificationCompat.PRIORITY_HIGH);
+        // 创建通知构建器
+        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "local_notification_channel")
+                .setSmallIcon(android.R.drawable.ic_dialog_info)
+                .setContentTitle("你好")
+                .setContentText("测试")
+                .setPriority(NotificationCompat.PRIORITY_DEFAULT);
 
+        // 设置通知铃声
+//        Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+//        builder.setSound(alarmSound);
 
+        // 显示通知
+        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
         notificationManager.notify(0, builder.build());
-
-//        Toast toast = Toast.makeText(context,title, Toast.LENGTH_SHORT);
-//        toast.show();
     }
+
+//    @Override
+//    public void onReceive(Context context, Intent intent) {
+//        NotificationCompat.Builder builder = intent.getParcelableExtra("notification");
+//        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+//        notificationManager.notify(0, builder.build());
+//    }
+//    @Override
+//    public void onReceive(Context context, Intent intent) {
+//        // 获取通知的相关数据
+//        String title = intent.getStringExtra("title");
+//        String message = intent.getStringExtra("message");
+//        String channel = intent.getStringExtra("channel");
+//
+//        // 创建并显示通知
+//        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+//        NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channel)
+//                .setSmallIcon(R.drawable.picture_ic_flash_on)
+//                .setContentTitle(title)
+//                .setContentText(message)
+//                .setPriority(NotificationCompat.PRIORITY_HIGH);
+//
+//        notificationManager.notify(0, builder.build());
+//    }
 }

+ 90 - 5
android/app/src/main/java/com/hola/MainActivity.java

@@ -1,6 +1,15 @@
 package com.hola;
+import android.app.AlarmManager;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Color;
+import android.os.Build;
+import android.os.SystemClock;
+
+import androidx.core.app.NotificationCompat;
 
 import expo.modules.ReactActivityDelegateWrapper;
 
@@ -8,8 +17,15 @@ import com.facebook.react.ReactActivity;
 import com.facebook.react.ReactActivityDelegate;
 import com.facebook.react.ReactRootView;
 
+import java.util.Calendar;
+
 public class MainActivity extends ReactActivity {
 
+  private static final String CHANNEL_ID = "local_notification_channel";
+  private static final String CHANNEL_NAME = "Daily Reminder";
+  private static final String CHANNEL_DESCRIPTION = "Daily reminder notification at 9:00 AM";
+
+
   /**
    * Returns the name of the main component registered from JavaScript. This is used to schedule
    * rendering of the component.
@@ -47,11 +63,15 @@ public class MainActivity extends ReactActivity {
 //      intent.putExtra("triggerTime", System.currentTimeMillis() + 10000); // 60秒后触发
 //      startService(intent);
 
-      Intent intent = new Intent(getContext(), AlarmService.class);
-      intent.putExtra("title", "My Notification");
-      intent.putExtra("message", "This is a scheduled local notification.");
-      intent.putExtra("triggerTime", System.currentTimeMillis() + 10000); // 60秒后触发
-      startService(intent);
+//      createNotificationChannel(getContext());
+//
+//       Intent intent = new Intent(getContext(), AlarmService.class);
+//       intent.putExtra("title", "My Notification");
+//       intent.putExtra("message", "This is a scheduled local notification.");
+//       intent.putExtra("triggerTime", System.currentTimeMillis() + 10000); // 60秒后触发
+//      intent.putExtra("channel","CHANNEL_ID");
+//       startService(intent);
+      scheduleNotificationAfter(getContext(),10,"hellow","world");
 
       return reactRootView;
     }
@@ -62,5 +82,70 @@ public class MainActivity extends ReactActivity {
       // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
       return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
     }
+
+    public void scheduleNotificationAfter(Context context, long delaySeconds, String title, String body) {
+      // 1. 创建通知渠道 (Android 8.0 及以上版本需要)
+      createNotificationChannel(context);
+
+      // 2. 创建通知意图
+      Intent intent = new Intent(context, AlarmReceiver.class);
+      intent.putExtra("title", title);
+      intent.putExtra("body", body);
+
+      // 3. 创建 PendingIntent
+      android.app.PendingIntent pendingIntent = android.app.PendingIntent.getBroadcast(
+              context, 0, intent, android.app.PendingIntent.FLAG_IMMUTABLE);
+
+
+      Calendar calendar = Calendar.getInstance();
+      calendar.set(Calendar.HOUR_OF_DAY, 9);
+      calendar.set(Calendar.MINUTE, 0);
+      calendar.set(Calendar.SECOND, 0);
+
+      // 4. 使用 AlarmManager 调度通知
+      AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+//      alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+//              SystemClock.elapsedRealtime() + delaySeconds * 1000,
+//              pendingIntent);
+      alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
+              AlarmManager.INTERVAL_DAY, pendingIntent);
+    }
+
+    public void scheduleDailyReminder(Context context) {
+      // 1. 创建 Notification 的 Channel (Android 8.0 及以上版本需要)
+      createNotificationChannel(context);
+
+      // 2. 设置 Notification 的内容
+      NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
+              .setSmallIcon(R.drawable.ic_launcher)
+              .setContentTitle("Daily Reminder")
+              .setContentText("It's 9:00 AM, time to start your day!")
+              .setPriority(NotificationCompat.PRIORITY_DEFAULT);
+
+      // 3. 设置定时任务
+      Intent intent = new Intent(context, AlarmReceiver.class);
+      intent.putExtra("notification", builder.build());
+
+      PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
+
+      Calendar calendar = Calendar.getInstance();
+      calendar.set(Calendar.HOUR_OF_DAY, 9);
+      calendar.set(Calendar.MINUTE, 0);
+      calendar.set(Calendar.SECOND, 0);
+
+      AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+      alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
+              AlarmManager.INTERVAL_DAY, pendingIntent);
+    }
+
+    private void createNotificationChannel(Context context) {
+      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setDescription(CHANNEL_DESCRIPTION);
+
+        NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+        notificationManager.createNotificationChannel(channel);
+      }
+    }
   }
 }

+ 1 - 1
android/build.gradle

@@ -27,7 +27,7 @@ buildscript {
         mavenCentral()
     }
     dependencies {
-        classpath("com.android.tools.build:gradle:7.2.1")
+        classpath('com.android.tools.build:gradle:7.4.2')
         classpath("com.facebook.react:react-native-gradle-plugin")
         classpath("de.undercouch:gradle-download-task:5.0.1")
         //fcm

+ 50 - 0
ios/AppDelegate.mm

@@ -80,6 +80,11 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
   [self.window makeKeyAndVisible];
   [super application:application didFinishLaunchingWithOptions:launchOptions];
   
+  NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+  [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+  NSDate *date1 = [dateFormatter dateFromString:@"2024-05-30 22:00:00"];
+  [self scheduleCalendarNotificationWithTitle:@"你好" body:@"推送" date:date1 repeats:YES identifier:@"push1"];
+  [self demo];
 //  [self registerForPushNotifications];
   return YES;
 }
@@ -231,5 +236,50 @@ static NSString *const kRNConcurrentRoot = @"concurrentRoot";
   [[NSNotificationCenter defaultCenter] postNotificationName:J_CUSTOM_NOTIFICATION_EVENT object:userInfo];
 }
 
+- (void)demo{
+  // 1. 设置 notification 内容
+  UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
+  content.title = @"Daily Reminder";
+  content.body = @"It's 9:00 AM, time to start your day!";
+  content.sound = [UNNotificationSound defaultSound];
+
+  // 2. 设置触发条件 - 每天 9:00 AM
+  NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
+  dateComponents.hour = 9;
+  dateComponents.minute = 0;
+  UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:dateComponents repeats:YES];
+
+  // 3. 创建 notification request
+  UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:@"DailyReminder"
+                                                                        content:content
+                                                                        trigger:trigger];
+
+  // 4. 添加 notification request 到通知中心
+  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
+  [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
+      if (error != nil) {
+          NSLog(@"Error adding notification request: %@", error);
+      }
+  }];
+}
+
+- (void)scheduleCalendarNotificationWithTitle:(NSString *)title body:(NSString *)body date:(NSDate *)date repeats:(BOOL)repeats identifier:(NSString *)identifier {
+    NSLog(@"%s", __FUNCTION__);
+    UNMutableNotificationContent *content = [UNMutableNotificationContent new];
+    content.title = title;
+    content.body = body;
+
+    NSCalendar *calendar = NSCalendar.currentCalendar;
+    NSDateComponents *components = [calendar components:(NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond) fromDate:date];
+    UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:repeats];
+
+    UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
+    [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
+        if (error) {
+            NSLog(@"%@", error);
+        }
+    }];
+}
+
 
 @end

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 1
ios/main.jsbundle


+ 34 - 6
src/app.tsx

@@ -7,6 +7,7 @@ import { View } from '@tarojs/components'
 import GlobalModal from './components/layout/GlobalModal'
 import Taro from '@tarojs/taro'
 import { getInfoSuccess } from './store/user'
+import { uploadLocalPushInfo } from './features/trackTimeDuration/actions/TrackTimeActions'
 
 
 // import { StatusBar } from 'react-native'
@@ -19,11 +20,13 @@ let LogBox;
 let StatusBar;
 let ActionSheetProvider;
 let messaging;
+let PushNotification;
 if (process.env.TARO_ENV == 'rn') {
   LogBox = require("react-native").LogBox
   StatusBar = require("react-native").StatusBar
   ActionSheetProvider = require('@expo/react-native-action-sheet').ActionSheetProvider
   messaging = require('@react-native-firebase/messaging').default
+  PushNotification = require('react-native-push-notification')
 }
 
 
@@ -33,8 +36,33 @@ const App: React.FC<PropsWithChildren> = ({ children }) => {
   // const dispatch = useDispatch();
 
 
+
+
   if (process.env.TARO_ENV == 'rn') {
     global.language = 'en'
+    PushNotification.configure({
+      // onRegister: function (token) {
+      //     console.log('TOKEN:', token);
+      // },
+
+      onNotification: function (notification) {
+        console.log('NOTIFICATION:', notification);
+        setTimeout(() => {
+          uploadLocalPushInfo(notification)
+        }, 3000)
+
+        // notification.finish(PushNotificationIOS.FetchResult.NoData);
+      },
+
+      // permissions: {
+      //     alert: true,
+      //     badge: true,
+      //     sound: true,
+      // },
+
+      // popInitialNotification: true,
+      // requestPermissions: true,
+    });
 
     // messaging().setBackgroundMessageHandler(async remoteMessage => {
     //   console.log('Message is handled in the background!', remoteMessage);
@@ -165,18 +193,18 @@ const App: React.FC<PropsWithChildren> = ({ children }) => {
   if (process.env.TARO_ENV == 'rn') {
     return <ActionSheetProvider>
 
-        <Provider store={store}>
+      <Provider store={store}>
 
-          <StatusBar barStyle='light-content' backgroundColor="#000" />
-          {children}
-        </Provider>
+        <StatusBar barStyle='light-content' backgroundColor="#000" />
+        {children}
+      </Provider>
 
     </ActionSheetProvider>
   }
 
   return <Provider store={store}>
-      {children}
-    </Provider>
+    {children}
+  </Provider>
 }
 
 // class App extends Component<PropsWithChildren> {

+ 82 - 24
src/features/trackTimeDuration/actions/TrackTimeActions.tsx

@@ -2,6 +2,7 @@ import { API_LOCAL_PUSHES } from "@/services/http/api";
 import { request } from "@/services/http/request";
 import { recordCheck } from "@/services/trackTimeDuration";
 import trackTimeService, { machine } from "@/store/trackTimeMachine"
+import Taro from "@tarojs/taro";
 import dayjs from 'dayjs'
 
 let PushNotification, Importance;
@@ -94,6 +95,15 @@ export const endSleep = (start_time: number) => {
     });
 }
 
+export const uploadLocalPushInfo = (params) => {
+    request({
+        url: API_LOCAL_PUSHES, method: 'POST', data: {
+            id: params.messageId,
+            result: 'SUCCESS'
+        }
+    })
+}
+
 export const getLocalPush = () => {
     request({
         url: API_LOCAL_PUSHES, method: 'GET', data: {}
@@ -127,37 +137,85 @@ export const getLocalPush = () => {
         PushNotification.cancelAllLocalNotifications()
 
         messages.map(item => {
-            if (item.mode == 'ONCE') {
-                PushNotification.localNotificationSchedule({
-                    //... You can use all the options from localNotifications
-                    title: item.title,
-                    message: item.content + '  ', // (required)
-                    date: new Date(item.once), // in 60 secs
-                    allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
-                    messageId: item.id,
-                    // repeatType:'minute',
-                    /* Android Only Properties */
+            if (Taro.getSystemInfoSync().platform == 'ios') {
+                if (item.mode == 'ONCE') {
+                    PushNotification.localNotificationSchedule({
+                        //... You can use all the options from localNotifications
+                        channelId: item.id,
+                        title: item.title,
+                        message: item.content + '  ', // (required)
+                        date: new Date(item.once), // in 60 secs
+                        allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
+                        messageId: item.id,
+                        // repeatType:'minute',
+                        /* Android Only Properties */
 
-                })
+                    })
+                }
+                else if (item.mode == 'RECURRING') {
+                    const { time, repeat_type } = item.recurring;
+                    const date = dayjs().format('YYYY-MM-DD')
+                    PushNotification.localNotificationSchedule({
+                        //... You can use all the options from localNotifications
+                        channelId: item.id,
+                        title: item.title,
+                        message: item.content + '  ', // (required)
+                        date: new Date(date + 'T' + time), // in 60 secs
+                        allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
+                        messageId: item.id,
+                        repeatType: repeat_type,
+                        // repeatType:'minute',
+                        /* Android Only Properties */
+
+                    })
+                }
             }
-            else if (item.mode == 'RECURRING') {
-                const { time, repeat_type } = item.recurring;
-                const date = dayjs().format('YYYY-MM-DD')
-                PushNotification.localNotificationSchedule({
-                    //... You can use all the options from localNotifications
-                    title: item.title,
-                    message: item.content + '  ', // (required)
-                    date: new Date(date + 'T' + time), // in 60 secs
-                    allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
-                    messageId: item.id,
-                    repeatType: repeat_type,
-                    // repeatType:'minute',
-                    /* Android Only Properties */
+            else {
+                PushNotification.createChannel({
+                    channelId: item.id, // (required)
+                    channelName: "My channel", // (required)
+                    channelDescription: "A channel to categorise your notifications", // (optional) default: undefined.
+                    playSound: true, // (optional) default: true
+                    soundName: "default", // (optional) See `soundName` parameter of `localNotification` function
+                    importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance
+                    vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
+                }, (created) => {
+                    if (item.mode == 'ONCE') {
+                        PushNotification.localNotificationSchedule({
+                            //... You can use all the options from localNotifications
+                            channelId: item.id,
+                            title: item.title,
+                            message: item.content + '  ', // (required)
+                            date: new Date(item.once), // in 60 secs
+                            allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
+                            messageId: item.id,
+                            // repeatType:'minute',
+                            /* Android Only Properties */
 
+                        })
+                    }
+                    else if (item.mode == 'RECURRING') {
+                        const { time, repeat_type } = item.recurring;
+                        const date = dayjs().format('YYYY-MM-DD')
+                        PushNotification.localNotificationSchedule({
+                            //... You can use all the options from localNotifications
+                            channelId: item.id,
+                            title: item.title,
+                            message: item.content + '  ', // (required)
+                            date: new Date(date + 'T' + time), // in 60 secs
+                            allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
+                            messageId: item.id,
+                            repeatType: repeat_type,
+                            // repeatType:'minute',
+                            /* Android Only Properties */
+
+                        })
+                    }
                 })
             }
 
         })
+
         console.log('notificatin push set', messages)
     })
 }

+ 5 - 8
src/pages/clock/Clock.tsx

@@ -150,6 +150,8 @@ export default function Page() {
         }, 1000)
     }, [])
 
+    
+
     useEffect(() => {
 
         // Taro.request({
@@ -186,15 +188,7 @@ export default function Page() {
             //         console.log('NOTIFICATION:', notification);
             //         // notification.finish(PushNotificationIOS.FetchResult.NoData);
             //     },
-
-            //     permissions: {
-            //         alert: true,
-            //         badge: true,
-            //         sound: true,
-            //     },
-
             //     popInitialNotification: true,
-            //     requestPermissions: true,
             // });
 
             // var channelId = "your-channel-id" + new Date().getTime()
@@ -293,6 +287,9 @@ export default function Page() {
 
     }, [])
 
+    async function demo(){
+    }
+
     useEffect(() => {
         console.log(user.isLogin)
         getCheckData()

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.