Vala hide Gtk.InfoBar after a few seconds - glib

In my Vala program I'm showing a Gtk.InfoBar when the user clicked a button.
Now I want to autohide the Gtk.InfoBar after a few seconds and put the focus back to the default Gtk.Entry.
After some research I think it is best to do this with GLib.Timeout, but the Valadoc.org-Documentation on this is not very helpful.
Also I was not able to find some Examples on the Internet.
Can someone tell me how to do this?
This is my source:
namespace Zeiterfassunggtk {
[GtkTemplate (ui = "/org/gnome/Zeiterfassunggtk/window.ui")]
public class Window : Gtk.ApplicationWindow {
[GtkChild]
Gtk.TreeView treeview1 = new Gtk.TreeView ();
[GtkChild]
Gtk.Button refreshbutton;
[GtkChild]
Gtk.MenuButton menubutton;
[GtkChild]
Gtk.Button menubuttonrefresh;
[GtkChild]
Gtk.Button menubuttonsave;
[GtkChild]
Gtk.Button menubuttonquit;
[GtkChild]
Gtk.InfoBar infobar1;
[GtkChild]
Gtk.Label infobar1label;
[GtkChild]
Gtk.Entry user_entry;
[GtkChild]
Gtk.Entry job_entry;
[GtkChild]
Gtk.Button addbutton;
Gtk.TreeIter iter;
Gtk.ListStore liststore1 = new Gtk.ListStore (3, typeof (string), typeof (string), typeof (string));
private void setup_treeview (Gtk.TreeView treeview1) {
treeview1.set_model (liststore1);
treeview1.insert_column_with_attributes (-1, "Name", new Gtk.CellRendererText (), "text", 0, null);
treeview1.insert_column_with_attributes (-1, "Job", new Gtk.CellRendererText (), "text", 1, null);
treeview1.insert_column_with_attributes (-1, "Time", new Gtk.CellRendererText (), "text", 2, null);
liststore1.append (out iter);
liststore1.set (iter, 0, "Gerald", 1, "Job1", 2, "2018-01-01 18:23", -1);
}
void refresh () {
liststore1.append (out iter);
liststore1.set (iter, 0, "Gerald", 1, "Job1", 2, "2018-01-01 18:23", -1);
infobar1.set_revealed (true);
infobar1label.set_label ("Refreshed!");
}
void save () {
liststore1.append (out iter);
liststore1.set (iter, 0, "Gerald", 1, "Job2", 2, "2018-01-01 24:00", -1);
user_entry.set_text ("");
job_entry.set_text ("");
user_entry.grab_default ();
infobar1.set_revealed (true);
infobar1label.set_label ("Saved!");
}
void hideinfobar () {
infobar1.set_revealed (false);
infobar1label.set_label ("Close");
}
public Window (Gtk.Application app) {
Object (application: app);
this.maximize ();
this.setup_treeview (treeview1);
// Don't show infobar1 on start
infobar1.set_revealed (false);
// Close infobar1 when Esc is hit.
infobar1.close.connect (this.hideinfobar);
// Close infobar1 when the close button is clicked.
infobar1.response.connect (this.hideinfobar);
refreshbutton.clicked.connect (this.refresh);
menubuttonrefresh.clicked.connect (this.refresh);
menubuttonsave.clicked.connect (this.save);
menubuttonquit.clicked.connect (app.quit);
addbutton.clicked.connect (this.save);
job_entry.set_activates_default (true);
job_entry.activate.connect (this.save);
user_entry.activate.connect (job_entry.grab_focus_without_selecting);
this.show_all ();
}
}
}
You can find the full source on github.com

With the help of Jens Mühlenhoff this is a working code:
namespace Zeiterfassunggtk {
[GtkTemplate (ui = "/org/gnome/Zeiterfassunggtk/window.ui")]
public class Window : Gtk.ApplicationWindow {
[GtkChild]
Gtk.Button button1;
[GtkChild]
Gtk.InfoBar infobar1;
[GtkChild]
Gtk.Label infobar1label;
public void hideinfobar () {
infobar1.set_revealed (false);
infobar1label.set_label ("");
}
public void showinfobar (string message) {
infobar1label.set_label (message);
infobar1.set_revealed (true);
Timeout.add_seconds (5, () => {
this.hideinfobar ();
return false;
});
}
public Window (Gtk.Application app) {
Object (application: app);
// Don't show infobar1 on start
this.hideinfobar ();
// Close infobar1 when Esc is hit.
infobar1.close.connect (this.hideinfobar);
// Close infobar1 when the close button is clicked.
infobar1.response.connect (this.hideinfobar);
// Connect Button and show infobar1
button1.clicked.connect (() => {
this.showinfobar ("Message");
});
this.show_all ();
}
}
}

You can use GLib.Timeout like this:
Timeout.add_seconds (5, () => {
stdout.printf ("Hello from timeout");
return false;
});
This will print a message in approximately 5 seconds. It only works when a MainLoop is already running (which is the case for every Gtk application).

Related

Custom iOS notifications sound local notifications package Flutter

I'm using Firebase Cloud Messaging to send notifications to my flutter app, and I'm using the flutter_local_notifications package to handle them, but when I tried to change the default notification sound it worked for android but didn't work for iOS, keep in mind that I add the "sound.aiff" to the root of the native iOS project, can anyone show me what I'm missing here, and thanks in advance
class FCMFunctions {
static final FCMFunctions _singleton = new FCMFunctions._internal();
FCMFunctions._internal();
factory FCMFunctions() {
return _singleton;
}
late FirebaseMessaging messaging;
//************************************************************************************************************ */
/// Create a [AndroidNotificationChannel] for heads up notifications
late AndroidNotificationChannel channel;
/// Initialize the [FlutterLocalNotificationsPlugin] package.
late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
//************************************************************************************************************ */
Future initApp() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
messaging = FirebaseMessaging.instance;
if (!kIsWeb) {
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
importance: Importance.high,
sound: RawResourceAndroidNotificationSound('sound'),
playSound: true,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
/// Create an Android Notification Channel.
///
/// We use this channel in the `AndroidManifest.xml` file to override the
/// default FCM channel to enable heads up notifications.
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
//for IOS Foreground Notification
await messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void initializeNotifications() async {
var initializationSettingsAndroid =
const AndroidInitializationSettings('icon');
var initializationSettingsIOS = const IOSInitializationSettings();
//var initializationSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
var initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: onSelectNotification,
);
}
Future onSelectNotification(String? payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
navigatorKey.currentState!.pushNamed(Routes.blackCurrency,
arguments: false); //message.data['category']
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Future subscripeToTopics(String topic) async {
await messaging.subscribeToTopic(topic);
}
///Expire : https://firebase.google.com/docs/cloud-messaging/manage-tokens
Future<String?> getFCMToken() async {
final fcmToken = await messaging.getToken();
return fcmToken;
}
void tokenListener() {
messaging.onTokenRefresh.listen((fcmToken) {
print("FCM Token dinlemede");
// TODO: If necessary send token to application server.
}).onError((err) {
print(err);
});
}
/// IOS
Future iosWebPermission() async {
if (Platform.isIOS || kIsWeb) {
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
}
}
///Foreground messages
///
///To handle messages while your application is in the foreground, listen to the onMessage stream.
void foreGroundMessageListener() {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print(
'///////////////////////////// NOTIFICATIONS ARE COMMING /////////////////////////////');
print('${message.notification!.body} ');
print("Message data type : ${message.data.runtimeType}");
var bodyRaw = message.data['body'];
var body = List<dynamic>.from(jsonDecode(bodyRaw ?? '[]'));
print("body : $body");
String bodyMessage = '';
if (body.first['sale'] == null) {
bodyMessage = body.first['name'];
} else if (body.first['name'] == null) {
bodyMessage = body.first['sale'];
} else {
bodyMessage =
body.map((e) => e['name'] + '-' + e['sale']).join(', ').toString();
}
RemoteNotification? notification = RemoteNotification(
android: const AndroidNotification(
smallIcon: 'assets/imgs/logo.png',
priority: AndroidNotificationPriority.highPriority,
visibility: AndroidNotificationVisibility.public,
),
apple: const AppleNotification(
sound: AppleNotificationSound(
name: 'sound',
volume: 1.0,
),
),
title: message.data['title'],
body: bodyMessage,
);
// message.notification;
AndroidNotification? android =
notification.android; //message.notification?.android;
if (notification != null && android != null && !kIsWeb) {
flutterLocalNotificationsPlugin.show(
notification.hashCode,
notification.title,
notification.body,
NotificationDetails(
android: AndroidNotificationDetails(
channel.id,
channel.name,
channelDescription: channel.description,
importance: Importance.max,
priority: Priority.max,
ticker: 'ticker',
sound: const RawResourceAndroidNotificationSound('sound'),
// icon: "#mipmap/icon",
playSound: true,
styleInformation: const DefaultStyleInformation(true, true),
),
iOS: const IOSNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
sound: 'sound',
),
),
);
}
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print('A new onMessageOpenedApp event was published!');
navigatorKey.currentState!.pushNamed(Routes.blackCurrency,
arguments: false); //message.data['category']
// Navigator.pushNamed(
// context,
// '/message',
// arguments: MessageArguments(message, true),
// );
});
}
}
final fcmFunctions = FCMFunctions();
Your server administrator will send you the sound name in notification payload which you added in iOS folder. Payload will look like this
{
aps =
{
alert = "notification message";
sound = "example.caf";
};
}
more information check this reference link
49
49
custom sound file for your app, follow this apple documentation.

flutter_local_notifications does not show the notification(IOS only)

i am beginner in flutter. I try to make an app which should notify users on scheduled time. I decided to use flutter_local_notification.
(I am trying to implement this only IOS as first step so that is why code blocks related with android commented in.)
class NotificationHelper {
FlutterLocalNotificationsPlugin
flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
initializeNotification() async {
//tz.initializeTimeZones();
final IOSInitializationSettings initializationSettingsIOS =
IOSInitializationSettings(
requestSoundPermission: false,
requestBadgePermission: false,
requestAlertPermission: false,
onDidReceiveLocalNotification: onDidReceiveLocalNotification
);
// final Android InitializationSettings initializationSettingsAndroid =
// Android InitializationSettings("appicon");
final InitializationSettings initializationSettings =
InitializationSettings(
iOS: initializationSettingsIOS,
);
await flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: selectNotification);
}
onDidReceiveLocalNotification(
int id, String? title, String? body, String? payload) async {
// display a dialog with the notification details, tap ok to go to another page
// showDialog(
// //context: context,
// builder: (BuildContext context) => CupertinoAlertDialog(
// title: Text(title),
// content: Text(body),
// actions: [
// CupertinoDialogAction(
// isDefaultAction: true,
// child: Text('Ok'),
// onPressed: () async {
// Navigator.of(context, rootNavigator: true).pop();
// await Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => SecondScreen(payload),
// ),
// );
// },
// )
// ],
// ),
// );
}
Future selectNotification(String? payload) async {
if (payload != null) {
print('notification payload: $payload');
} else {
print("Notification Done");
}
}
void requestIOSPermissions() {
flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
IOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
}
displayNotification({required String title, required String body}) async {
print("doing test");
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails('your channel id', 'your channel name',
channelDescription: 'your channel description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
flutterLocalNotificationsPlugin.show(
12345,
"A Notification From My Application",
"This notification was sent using Flutter Local Notifcations Package",
platformChannelSpecifics,
payload: 'data');
}
}
and i call the initializeNotification() function on my main.dart like this:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
NotificationHelper().requestIOSPermissions();
NotificationHelper().initializeNotification();
runApp(const MyApp());
}
and after user logged in,
I just try to see my notification so i call displayNotification() on a button like this:
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
NotificationHelper().displayNotification(title: 'title', body: 'hede');
},
color: Colors.white,
iconSize: 25,
),
and also i call this code in AppDelegate.swift
import UIKit
import Flutter
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
when application opens it successfully asks permissions for send notifications. After it allowed i just try to call displayNotification() but it doesn't work. I cannot see any notification on my simulator.
environment:
sdk: ">=2.15.1 <3.0.0"
flutter_local_notifications: ^9.3.3
What should i do ? Thank you for you all your answers.
I think notifications doesn't work currently on İOS simulator. You should try real ios device

Vaadin 14 - Error: Detected container element removed from DOM

Update 1: ============
After remove "window.ShadyDOM={force:true};" then it worked. But this is causing other problem ;):
https://vaadin.com/forum/thread/17399734/leverage-browser-save-password-feature
#Override
public void configurePage(InitialPageSettings settings) {
// TODO Auto-generated method stub
settings.addMetaTag("mobile-web-app-capable", "yes");
settings.addMetaTag("apple-mobile-web-app-capable", "yes");
settings.addMetaTag("apple-mobile-web-app-status-bar-style", "black");
settings.addInlineWithContents(
InitialPageSettings.Position.PREPEND, "window.customElements=window.customElements||{};"
+ "window.customElements.forcePolyfill=true;" + "window.ShadyDOM={force:true};",
InitialPageSettings.WrapMode.JAVASCRIPT);
}
End Update. ============
I am trying to integrate Payal checkout to Vaadin 14.7 (Spring core, not spring boot).
Here is paypal-view.js
import { LitElement, html, css } from "lit-element";
let buttons;
let hasRendered = false;
class PaypalElement extends LitElement {
static get properties() {
return {
mood: {
type: String,
noAccessor: false,
hasChanged(newVal, oldVal) {
console.log("newVal " + newVal + " oldVal " + oldVal);
},
},
};
}
static get styles() {
return [
css`
mood_color {
color: green;
}
#paypal-button {
size: "responsive";
}
`,
];
}
firstUpdated(_changedProperties) {
let testFname = this.shadowRoot.getElementById("fname");
super.firstUpdated(_changedProperties);
if (buttons && buttons.close && hasRendered) {
buttons.close();
hasRendered = false;
}
buttons = window.paypal.Buttons({
// Set up the transaction
createOrder: function (data, actions) {
return actions.order.create({
application_context: {
brand_name: "Brand name",
user_action: "PAY_NOW",
//No shipping for in-tangible merchant
shipping_preference: "NO_SHIPPING",
payment_method: {
payee_preferred: "IMMEDIATE_PAYMENT_REQUIRED", // Pending status transactions will not be allowed if you pass this parameter.
payer_selected: "PAYPAL",
},
},
purchase_units: [
{
soft_descriptor: "CC_STATEMENT_NAME",
amount: {
value: "5.00",
},
},
],
});
},
// Finalize the transaction
onApprove: function (data, actions) {
const elementText = document.getElementById("fname");
return actions.order.capture().then(function (orderData) {
// Successful capture! For demo purposes:
console.log(
"Capture result",
orderData,
JSON.stringify(orderData, null, 2)
);
let transaction = orderData.purchase_units[0].payments.captures[0];
// Replace the above to show a success message within this page, e.g.
// const element = document.getElementById('paypal-button-container');
// element.innerHTML = '';
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
// Or go to another URL: actions.redirect('thank_you.html');
document.getElementById("update-paypal-trans").innerHTML =
"update-paypal-trans = " + transaction.id;
// trigger lit event
testFname.value = transaction.id;
testFname.click();
document.getElementById("paypalelement").remove();
//console.log(elementText);
});
},
onError: function (error) {
console.log("onError", error, JSON.stringify(error, null, 2));
},
onCancel: function (data, actions) {
console.log("onCancel", data, JSON.stringify(data, null, 2));
document.getElementById("update-paypal-trans").innerHTML =
"testing 123";
// update shadow element
testFname.value = "12345 " + actions;
// trigger lit event
testFname.click();
},
});
// load paypal buttons and put them to element id="paypal-button-to-display" which is shadow dom
buttons
.render(this.shadowRoot.getElementById("paypal-button-to-display"))
.then(() => {
hasRendered = true;
})
.catch((err) => {
console.log(err)
// not mounted anymore, we can safely ignore the error
return;
});
}
// outside updates shadow element
updateShadow() {
this.shadowRoot.getElementById("test-update-shadow").innerHTML =
"test update shadow trans";
this.mood = "nice";
}
updateTask(e) {
console.log("updateTask: " + e);
}
updateTaskClick(e) {
console.log("updateTaskClick: " + e);
// call back-end
}
render() {
return html`
Web Components are
<span class="mood_color"> ${this.mood} and ${this.innerHTML}</span>!
<input
type="text"
id="fname"
name="fname"
value="${this.mood}"
#change=${(e) => this.updateTask(e.target.value)}
#click="${(e) => this.updateTaskClick(e.target.value)}"
/>
<div id="paypal-button-to-display"></div>
<br />
<div id="test-update-shadow">test-update-shadow-default</div>
<br />
<input
#click="${() => this.updateShadow()}"
id="myinput"
type="button"
value="update shadow button"
/>
`;
}
attributeChangedCallback(name, oldval, newval) {
super.attributeChangedCallback(name, oldval, newval);
console.log("attribute change: ", name, newval);
}
changeProperties() {
let randomString = Math.floor(Math.random() * 100).toString();
this.mood = "myProp " + randomString;
console.log("randomString change: ", randomString);
}
}
customElements.define("paypal-element", PaypalElement);
hello-world-view.ts
import { html, LitElement, customElement } from 'lit-element';
import './paypal-view';
import '#vaadin/vaadin-button';
import '#vaadin/vaadin-text-field';
#customElement('hello-world-view')
export class HelloWorldView extends LitElement {
createRenderRoot() {
// Do not use a shadow root
return this;
}
constructor() {
super();
}
render() {
return html`
<vaadin-text-field id="name" label="Your name"></vaadin-text-field>
<vaadin-button >Say hello</vaadin-button>
<paypal-elementt mood="great" id="paypalBut">hello customer</paypal-elementt>
`;
}
}
hello-world-view.ts
package com.lecompany.iad.view;
import com.lecompany.iad.app.MainView;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.littemplate.LitTemplate;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.template.Id;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouteAlias;
/**
* A Designer generated component for the stub-tag template.
*
* Designer will add and remove fields with #Id mappings but does not overwrite
* or otherwise change this file.
*/
#PageTitle("Hello World")
#Route(value = "hello", layout = MainView.class)
#Tag("hello-world-view")
#JsModule("./src/view/hello-world-view.ts")
public class HelloWorldView extends LitTemplate {
#Id
private TextField name;
// #Id
// private Button sayHello;
public HelloWorldView() {
UI.getCurrent().getPage().addJavaScript("https://www.paypal.com/sdk/js?client-id=AejZZjQsvxS299I2_LSnRkJStp0AsBzScCqbGK1_W6RNJssNR5NVnKYd97dM2kOJnRMF1u1ldLGjOlZ5&currency=USD");
// sayHello.addClickListener(e -> {
// Notification.show("Hello " + name.getValue());
// });
}
}
And here is error:
I tested above codes in Spring boot, then it works fine.
but it got error in the normal spring code. Any advice on this ?
There is reported issue for Paypal.
Paypal reported issue
It is a Vaadin bug and reported here:
Vaadin bug

Remote video from Safari iPhone showing black-screen [duplicate]

iPhone safari version: 11.2.5
Chrome version: Checking for updates Version 80.0.3987.163 (Official Build) (64-bit)
The connection is a peer to peer.
If I can give you an overview it's like -
Video is coming on iPhone from mac safari, Chrome, window laptop
Video is coming on Android Phone from mac safari, Chrome, window laptop
Video is coming on mac safari, Chrome, window laptop from Android Phone
Video is NOT COMING on mac safari, Chrome, window laptop from iPhone
Please let me know if you can help. Thanks in advance.
I solve this issue
createLocalVideoTrack({
video: { width: 1280, height: 720 },
}).then(track => {
if (this.localVideo) {
const element = track.attach();
this.renderer.data.id = track.sid;
this.renderer.setStyle(element, 'width', '25%');
this.renderer.appendChild(this.localVideo.nativeElement, element);
this.attachVideoClass();
}
});
Should be :
this.roomObj.localParticipant.videoTracks.forEach(publication => {
const element = publication.track.attach();
this.renderer.data.id = publication.track.sid;
this.renderer.setStyle(element, 'width', '25%');
this.renderer.appendChild(this.localVideo.nativeElement, element);
})
Twilio developer evangelist here.
I would recommend reading through the developing for Safari 11 article which goes over a bunch of potential issues.
Please check code:
import { Injectable, EventEmitter, ElementRef, Renderer2, RendererFactory2 } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs';
import { connect, createLocalTracks, createLocalVideoTrack } from 'twilio-video';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Http } from '#angular/http';
import { Router } from '#angular/router';
import { BaCustomPreLoader } from './baCustomPreloader.service';
#Injectable()
export class TwilioService {
remoteVideo: ElementRef;
localVideo: ElementRef;
previewing: boolean;
msgSubject = new BehaviorSubject("");
roomObj: any;
roomParticipants;
private renderer: Renderer2;
constructor(
private http: Http,
private router: Router,
private rendererFactory: RendererFactory2,
private baCustomPreLoader: BaCustomPreLoader) {
this.renderer = rendererFactory.createRenderer(null, null);
}
getToken(username): Observable<any> {
return this.http.post('/abc', { uid: 'ashish' });
}
microphone = true;
mute() {
this.roomObj.localParticipant.audioTracks.forEach(function (
audioTrack
) {
audioTrack.track.disable();
});
this.microphone = false;
}
unmute() {
this.roomObj.localParticipant.audioTracks.forEach(function (
audioTrack,
key,
map
) {
audioTrack.track.enable();
});
this.microphone = true;
}
connectToRoom(accessToken: string, options): void {
connect(accessToken, options).then(room => {
this.roomObj = room;
if (!this.previewing && options['video']) {
this.startLocalVideo();
this.previewing = true;
}
this.roomParticipants = room.participants;
room.participants.forEach(participant => {
this.attachParticipantTracks(participant);
});
room.on('participantDisconnected', (participant) => {
this.detachParticipantTracks(participant);
});
room.on('participantConnected', (participant) => {
this.roomParticipants = room.participants;
this.attachParticipantTracks(participant);
participant.on('trackAdded', track => {
const element = track.attach();
this.renderer.data.id = track.sid;
this.renderer.setStyle(element, 'height', '100%');
this.renderer.setStyle(element, 'max-width', '100%');
this.renderer.appendChild(this.remoteVideo.nativeElement, element);
this.attachVideoClass();
this.baCustomPreLoader.hide();
});
});
// When a Participant adds a Track, attach it to the DOM.
room.on('trackAdded', (track, participant) => {
this.attachTracks([track]);
});
// When a Participant removes a Track, detach it from the DOM.
room.on('trackRemoved', (track, participant) => {
this.detachTracks([track]);
});
room.once('disconnected', room => {
room.localParticipant.tracks.forEach(track => {
track.track.stop();
const attachedElements = track.track.detach();
attachedElements.forEach(element => element.remove());
room.localParticipant.videoTracks.forEach(video => {
const trackConst = [video][0].track;
trackConst.stop(); // <- error
trackConst.detach().forEach(element => element.remove());
room.localParticipant.unpublishTrack(trackConst);
});
let element = this.remoteVideo.nativeElement;
while (element.firstChild) {
element.removeChild(element.firstChild);
}
let localElement = this.localVideo.nativeElement;
while (localElement.firstChild) {
localElement.removeChild(localElement.firstChild);
}
this.router.navigate(['thanks']);
setTimeout(() => {
window.location.reload();
}, 1000)
});
});
}, (error) => {
alert(error.message);
});
}
attachParticipantTracks(participant): void {
participant.tracks.forEach(part => {
this.trackPublished(part);
});
}
trackPublished(publication) {
if (publication.isSubscribed)
this.attachTracks(publication.track);
if (!publication.isSubscribed)
publication.on('subscribed', track => {
this.attachTracks(track);
});
}
attachTracks(tracks) {
const element = tracks.attach();
this.renderer.data.id = tracks.sid;
this.renderer.setStyle(element, 'height', '100%');
this.renderer.setStyle(element, 'max-width', '100%');
this.renderer.appendChild(this.remoteVideo.nativeElement, element);
this.attachVideoClass();
this.baCustomPreLoader.hide();
}
startLocalVideo(): void {
createLocalVideoTrack({
video: { width: 1280, height: 720 },
}).then(track => {
if (this.localVideo) {
const element = track.attach();
this.renderer.data.id = track.sid;
this.renderer.setStyle(element, 'width', '25%');
this.renderer.appendChild(this.localVideo.nativeElement, element);
this.attachVideoClass();
}
});
}
detachParticipantTracks(participant) {
this.detachTracks(participant);
}
detachTracks(tracks): void {
tracks.tracks.forEach(track => {
let element = this.remoteVideo.nativeElement;
while (element.firstChild) {
element.removeChild(element.firstChild);
}
});
}
attachVideoClass() {
let remote = document.getElementById('remote');
}
}

Background service issue : App crush when using geolocator

I'm working on a fitness/health flutter app project.
My app work just works fine on android, but the app crashes and stops working immediately in ios when I'm invoking location service.
I have a button inside a map view page to start counting steps and time of the walking sessions.
My button's code
RaisedButton(
textColor: Colors.white,
color: checkRun == false
? Settings.mainColor()
: Colors.red,
child: Container(
padding: EdgeInsets.all(15),
child: checkRun == false
? Text(allTranslations.text("startNow"))
: Text(allTranslations.text("endNow"))),
onPressed: () async {
rightButtonPressed();
if (checkRun == false) {
getLocation();
} else if (checkRun == true) {
setState(() {
checkRun = false;
});
try {
FormData formdata = new FormData();
// get user token
SharedPreferences sharedPreferences =
await SharedPreferences.getInstance();
Map<String, dynamic> authUser = jsonDecode(
sharedPreferences
.getString("authUser"));
dio.options.headers = {
"Authorization":
"Bearer ${authUser['authToken']}",
};
formdata.add("startLongitude",
points.first.longitude);
formdata.add(
"endLongitude", points.last.longitude);
formdata.add(
"startLatitude", points.first.latitude);
formdata.add(
"endLatitude", points.last.latitude);
formdata.add("date", DateTime.now());
meter = distance.as(
lm.LengthUnit.Meter,
lm.LatLng(points.first.latitude,
points.first.longitude),
lm.LatLng(points.last.latitude,
points.last.longitude));
setState(() {});
print(meter);
formdata.add("distance", meter.toInt());
formdata.add("steps", _polylineIdCounter);
formdata.add("calories", (_polylineIdCounter*0.0512).toInt());
response = await dio.post(
"http://104.248.168.117/api/mapInformation",
data: formdata);
if (response.statusCode != 200 &&
response.statusCode != 201) {
return false;
} else {
print('success -->');
print('Response = ${response.data}');
return true;
}
} on DioError catch (e) {
return false;
}
}
// return true;
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)))
getLoaction code :
getLocation() {
setState(() {
checkRun = true;
});
print('CheckRun = > $checkRun');
// Fired whenever a location is recorded
bg.BackgroundGeolocation.onLocation((bg.Location location) {
print('[location] - $location');
print('<--------- start onLocation -----------> ');
print(location.coords.latitude);
print(location.coords.longitude);
print('<--------- End onLocation -----------> ');
if (checkRun == true) {
setState(() {
points.add(_createLatLng(
location.coords.latitude, location.coords.longitude));
print('Points=> $points');
_add();
});
} else if (checkRun == false) {
setState(() {
points.clear();
});
}
});
// Fired whenever the plugin changes motion-state (stationary->moving and vice-versa)
bg.BackgroundGeolocation.onMotionChange((bg.Location location) {
print('[motionchange] - $location');
print('<--------- Locaiton onMotionChange -----------> ');
updatelat=location.coords.latitude;
updatelong=location.coords.longitude;
setState(() {
});
print(location.coords.latitude);
print(location.coords.longitude);
print('<--------- / Locaiton onMotionChange -----------> ');
});
// Fired whenever the state of location-services changes. Always fired at boot
bg.BackgroundGeolocation.onProviderChange((bg.ProviderChangeEvent event) {
});
////
// 2. Configure the plugin
//
bg.BackgroundGeolocation.ready(bg.Config(
desiredAccuracy: bg.Config.DESIRED_ACCURACY_HIGH,
distanceFilter: 10.0,
stopOnTerminate: false,
startOnBoot: true,
debug: false,
logLevel: bg.Config.LOG_LEVEL_INFO,
reset: true))
.then((bg.State state) {
if (!state.enabled) {
////
// 3. Start the plugin.
//
print('[ready] success: $state');
bg.BackgroundGeolocation.start();
}
});}
I'm using these packages:
flutter_background_geolocation: ^1.2.4
geolocator: ^5.0.1
Map view is crushing in the release version because flutter_background_geolocation is required you to buy a license to make it work in release versions, so it will work fine with you when you build the app in debug mode but it will crush on release mode without a license.

Resources