istornz / flutter_live_activities

A Flutter plugin to use iOS 16.1+ Live Activities ⛹️ & iPhone Dynamic Island 🏝️ features
https://dimitridessus.fr/
MIT License
187 stars 56 forks source link

Dynamic Island interaction & ui not showing #57

Open Okunamutata opened 1 year ago

Okunamutata commented 1 year ago

I've implemented the plugin following the readme. I tried a few times on my project and the counter flutter template project.

After calling _liveActivitiesPlugin.init theres no error. But the return value of that function results to a null.

Im able to call createActivity and receive a String id value.

But nothing is happening visually.

I do see a widget can be added to the homescreen, but thats it.

Heres all the dart code. Any help would be really appreciated

  @override
  void initState() {
    init();
    super.initState();
  }

  @override
  void dispose(){
    _liveActivitiesPlugin.dispose(force: false);
    super.dispose();
  }

  Future<void> init()async{
    try{
      dynamic a  = await _liveActivitiesPlugin.init(
          appGroupId: 'group.<my_bundle_identifier>.sf', urlScheme: 'sf');
      log(a.toString());
    }catch(e){
      log(e.toString());
    }
    activity( widget.workout.exercises.first);
  }

  Future<void> activity(ExerciseModel exerciseModel, {int index = 0})async {
    final Map<String, dynamic> activityModel = {
      'name': 'Margherita',
      'ingredient': 'tomato, mozzarella, basil',
      'quantity': 1,
    };
    try{
      if (id == null) {
        id = await _liveActivitiesPlugin.createActivity(activityModel);
        log(id.toString());
      } else {
        await _liveActivitiesPlugin.updateActivity(id!, activityModel);

      }
    }catch(e){
      log(e.toString());
    }
  }
xTriple commented 1 year ago

Hi Okunamutata,

I had the same problem, and took me about a day to figure it out, and i have some tips for you:

  1. you don't need to wait for the activity that return
  2. try to move everything related to the liveActivity into the screen file
  3. check your model everything that seems like a special character such as ' , : and so on seems like out of reach, i had an error when i passed into the model '15:10' after i took it out, everything worked fine

  4. check into Xcode that you put Supports Live Activities on true in every info.plist

hope this helps

Okunamutata commented 1 year ago

Hey @xTriple thanks, i double check the configs and yea its working now. However im unable to read data from UserDefaults(suiteName: on the liveActivity swift file.

Here some of the code, Im able to see my values as createActivty & updateActivity is called. But not sure how to run dynamic island with a debugger ... any way the values default to my String literals

let sharedDefault = UserDefaults(suiteName: "group.<my_bundle_identifier>.sf")!

@available(iOSApplicationExtension 16.1, *)
struct WidgetLiveActivity: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in
            // Lock screen/banner UI goes here

            let heading = sharedDefault.string(forKey: "name") ?? "Workout in progress"

            let isRest = sharedDefault.bool(forKey: "rest") 
 final Map<String, dynamic> activityModel = <String, dynamic>{
        'name': exerciseModel.mvmt.title,
        'rest': exerciseModel.sets[index].isRest
      };
      try {
        if (id == null) {
          id = await _liveActivitiesPlugin.createActivity(
              activityModel, removeWhenAppIsKilled: true);
          log(id.toString());
        } else {
          await _liveActivitiesPlugin.updateActivity(id!, activityModel);
        }
      } catch (e) {
        log(e.toString());
      }

Any tips would be great 🌮

xTriple commented 1 year ago

Hey @Okunamutata, the only way for you to test your Dynamic island with a debugger is only by Xcode. If you think your problem is inside Xcode you can try to create an app iOS native and try from there. The only tip i can give you about it is:

Try to take the example project swift file (https://github.com/istornz/flutter_live_activities/blob/main/example/ios/extension-example/extension_example.swift), and set only the bundle id inside the UserDefaults, and then start working from there, i think is pretty easier instead of starting from 0, you should pass the same model (https://github.com/istornz/flutter_live_activities/blob/main/example/lib/models/football_game_live_activity_model.dart) and then if it works is just a matter of loosing time creating the dynamic island

let me know how it goes 🧐

Okunamutata commented 1 year ago

Hey @xTriple thanks. it seems to be an issue with kCFPreferencesAnyUser.

The the dart code init's the plugin this warning is shown in Xcode


Couldn't read values in CFPrefsPlistSource<0x2829e0990> (Domain: group.< my_bundle_identifier >.sf, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd


kartikeyaa-k commented 1 year ago

Hi @Okunamutata & @xTriple I am also facing the exact same issue, I have followed all the steps mentioned. However, nothing is displayed, although console does prints the activity Id, means the activity does get created but nothing on Lock Screen and dynamic island.

configs : Flutter : 3.13.0 Xcode : 14.1

Update : The sample app works as expected. I am going to debug and find the issue in my project. Please do provide any findings and I will do the same. Cheers.

xTriple commented 1 year ago

Hi @Okunamutata you can follow this thread for the solution (https://developer.apple.com/forums/thread/51348?page=2) in short if it doesn't crash it can be ignored otherwise try to set the team number, you should have something like 'teamNumber.group.< your_bundle_identifier >.sf'

@kartikeyaa-k for you i can say this:

  1. as for Okuna check your model, quickway is take the sample app and change the model to what you want.
  2. if you wanna pass a string or a date remember to pass it like the example i.e. with DateTime.now().milliseconds and for the image with LiveActivityImageFromAsset('< path to image >')
  3. be sure that the group id shows in white and not red in Xcode
  4. if you print the event in the "liveActivitiesPlugin.activitUpdateStream.listen" if it doesn't show in the console, something like: ActiveActivityUpdate(activityId: < activity id >, activityToken: < activity token > then there is something wrong dart side or in the Xcode configuration
kartikeyaa-k commented 1 year ago

Hey @xTriple thanks, i double check the configs and yea its working now. However im unable to read data from UserDefaults(suiteName: on the liveActivity swift file.

Here some of the code, Im able to see my values as createActivty & updateActivity is called. But not sure how to run dynamic island with a debugger ... any way the values default to my String literals

let sharedDefault = UserDefaults(suiteName: "group.<my_bundle_identifier>.sf")!

@available(iOSApplicationExtension 16.1, *)
struct WidgetLiveActivity: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in
            // Lock screen/banner UI goes here

            let heading = sharedDefault.string(forKey: "name") ?? "Workout in progress"

            let isRest = sharedDefault.bool(forKey: "rest") 
 final Map<String, dynamic> activityModel = <String, dynamic>{
        'name': exerciseModel.mvmt.title,
        'rest': exerciseModel.sets[index].isRest
      };
      try {
        if (id == null) {
          id = await _liveActivitiesPlugin.createActivity(
              activityModel, removeWhenAppIsKilled: true);
          log(id.toString());
        } else {
          await _liveActivitiesPlugin.updateActivity(id!, activityModel);
        }
      } catch (e) {
        log(e.toString());
      }

Any tips would be great 🌮

@xTriple I found the issue for my project and it is working now. @Okunamutata When you are parsing the data on swift side using key, can you try doing it this way :

let isRest: String = sharedDefault.string(forKey: 
            context.attributes.prefixedKey("rest"))!

instead of

let isRest = sharedDefault.bool(forKey: "rest")

and make sure you add the same extension at the bottom from sample file. Verify the name is correct for your project.

Thanks @xTriple

no-chili commented 10 months ago

Hey @xTriple thanks, i double check the configs and yea its working now. However im unable to read data from UserDefaults(suiteName: on the liveActivity swift file.嘿,谢谢,我仔细检查了配置,是的,它现在可以工作了。但是,我无法从 UserDefaults(suiteName: liveActivity swift 文件上读取数据。

Here some of the code, Im able to see my values as createActivty & updateActivity is called. But not sure how to run dynamic island with a debugger ... any way the values default to my String literals在这里的一些代码中,我能够看到我的值,因为 createActivty & updateActivity 被调用。但不确定如何使用调试器运行动态岛......无论如何,这些值默认为我的 String 文字

let sharedDefault = UserDefaults(suiteName: "group.<my_bundle_identifier>.sf")!

@available(iOSApplicationExtension 16.1, *)
struct WidgetLiveActivity: Widget {
    var body: some WidgetConfiguration {
        ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in
            // Lock screen/banner UI goes here

            let heading = sharedDefault.string(forKey: "name") ?? "Workout in progress"

            let isRest = sharedDefault.bool(forKey: "rest") 
 final Map<String, dynamic> activityModel = <String, dynamic>{
        'name': exerciseModel.mvmt.title,
        'rest': exerciseModel.sets[index].isRest
      };
      try {
        if (id == null) {
          id = await _liveActivitiesPlugin.createActivity(
              activityModel, removeWhenAppIsKilled: true);
          log(id.toString());
        } else {
          await _liveActivitiesPlugin.updateActivity(id!, activityModel);
        }
      } catch (e) {
        log(e.toString());
      }

Any tips would be great 🌮任何提示都会很棒 🌮

I added the following code to the swift file to extend the LiveActivitiesAppAttributes and got the value

extension LiveActivitiesAppAttributes {
  func prefixedKey(_ key: String) -> String {
    return "\(id)_\(key)"
  }
}
let emoji: String = sharedDefault.string(forKey:
                        context.attributes.prefixedKey("emoji"))!
Okunamutata commented 8 months ago

Hey @xTriple thanks, i double check the configs and yea its working now. However im unable to read data from UserDefaults(suiteName: on the liveActivity swift file.嘿,谢谢,我仔细检查了配置,是的,它现在可以工作了。但是,我无法从 UserDefaults(suiteName: liveActivity swift 文件上读取数据。

Here some of the code, Im able to see my values as createActivty & updateActivity is called. But not sure how to run dynamic island with a debugger ... any way the values default to my String literals在这里的一些代码中,我能够看到我的值,因为 createActivty & updateActivity 被调用。但不确定如何使用调试器运行动态岛......无论如何,这些值默认为我的 String 文字


let sharedDefault = UserDefaults(suiteName: "group.<my_bundle_identifier>.sf")!

@available(iOSApplicationExtension 16.1, *)

struct WidgetLiveActivity: Widget {

    var body: some WidgetConfiguration {

        ActivityConfiguration(for: LiveActivitiesAppAttributes.self) { context in

            // Lock screen/banner UI goes here

            let heading = sharedDefault.string(forKey: "name") ?? "Workout in progress"

            let isRest = sharedDefault.bool(forKey: "rest") 

 final Map<String, dynamic> activityModel = <String, dynamic>{

        'name': exerciseModel.mvmt.title,

        'rest': exerciseModel.sets[index].isRest

      };

      try {

        if (id == null) {

          id = await _liveActivitiesPlugin.createActivity(

              activityModel, removeWhenAppIsKilled: true);

          log(id.toString());

        } else {

          await _liveActivitiesPlugin.updateActivity(id!, activityModel);

        }

      } catch (e) {

        log(e.toString());

      }

Any tips would be great 🌮任何提示都会很棒 🌮

I added the following code to the swift file to extend the LiveActivitiesAppAttributes and got the value


extension LiveActivitiesAppAttributes {

  func prefixedKey(_ key: String) -> String {

    return "\(id)_\(key)"

  }

}

let emoji: String = sharedDefault.string(forKey:

                        context.attributes.prefixedKey("emoji"))!

Thanks. I appreciate the helper function. It works now.

adham-ashraf77 commented 5 months ago
  • be sure that the group id shows in white and not red in Xcode

I have the same issue how you solve it please @Okunamutata