Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 46 additions & 94 deletions packages/android_alarm_manager_plus/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,186 +1,138 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:developer' as developer;
import 'dart:isolate';
import 'dart:math';
import 'dart:ui';

import 'package:android_alarm_manager_plus/android_alarm_manager_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/material.dart';

/// The [SharedPreferences] key to access the alarm fire count.
const String countKey = 'count';

/// The name associated with the UI isolate's [SendPort].
const String isolateName = 'isolate';

/// A port used to communicate from a background isolate to the UI isolate.
ReceivePort port = ReceivePort();

/// Global [SharedPreferences] object.
SharedPreferences? prefs;
final ReceivePort port = ReceivePort();
late final SharedPreferences prefs;

/// Entry point of the app
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();

// Register the UI isolate's SendPort to allow for communication from the
// background isolate.
IsolateNameServer.registerPortWithName(
port.sendPort,
isolateName,
);
IsolateNameServer.registerPortWithName(port.sendPort, isolateName);

Check failure on line 24 in packages/android_alarm_manager_plus/example/lib/main.dart

View workflow job for this annotation

GitHub Actions / Dart Analyzer

Undefined name 'IsolateNameServer'.

Try correcting the name to one that is defined, or defining the name. See https://dart.dev/diagnostics/undefined_identifier to learn more about this problem.
prefs = await SharedPreferences.getInstance();
if (!prefs!.containsKey(countKey)) {
await prefs!.setInt(countKey, 0);
if (!prefs.containsKey(countKey)) {
await prefs.setInt(countKey, 0);
}

runApp(const AlarmManagerExampleApp());
}

/// Example app for Espresso plugin.
class AlarmManagerExampleApp extends StatelessWidget {
const AlarmManagerExampleApp({super.key});

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
title: 'Flutter Alarm Manager',
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: const Color(0x9f4376f8),
),
home: const _AlarmHomePage(),
home: const AlarmHomePage(),
);
}
}

class _AlarmHomePage extends StatefulWidget {
const _AlarmHomePage();
class AlarmHomePage extends StatefulWidget {
const AlarmHomePage({super.key});

@override
_AlarmHomePageState createState() => _AlarmHomePageState();

Check notice on line 53 in packages/android_alarm_manager_plus/example/lib/main.dart

View workflow job for this annotation

GitHub Actions / Dart Analyzer

Invalid use of a private type in a public API.

Try making the private type public, or making the API that uses the private type also be private. See https://dart.dev/diagnostics/library_private_types_in_public_api to learn more about this problem.
}

class _AlarmHomePageState extends State<_AlarmHomePage> {
class _AlarmHomePageState extends State<AlarmHomePage> {
int _counter = 0;
PermissionStatus _exactAlarmPermissionStatus = PermissionStatus.granted;
static SendPort? uiSendPort;

@override
void initState() {
super.initState();
AndroidAlarmManager.initialize();
_checkExactAlarmPermission();

// Register for events from the background isolate. These messages will
// always coincide with an alarm firing.
port.listen((_) async => await _incrementCounter());
port.listen((_) => _incrementCounter());
}

void _checkExactAlarmPermission() async {
final currentStatus = await Permission.scheduleExactAlarm.status;
Future<void> _checkExactAlarmPermission() async {
final status = await Permission.scheduleExactAlarm.status;
if (!mounted) return;
setState(() {
_exactAlarmPermissionStatus = currentStatus;
});
setState(() => _exactAlarmPermissionStatus = status);
}

Future<void> _incrementCounter() async {
developer.log('Increment counter!');
// Ensure we've loaded the updated count from the background isolate.
await prefs?.reload();

setState(() {
_counter++;
});
developer.log('Increment counter!', name: 'AlarmManagerExample');
await prefs.reload();
if (!mounted) return;
setState(() => _counter++);
}

// The background
static SendPort? uiSendPort;

// The callback for our alarm
@pragma('vm:entry-point')
static Future<void> callback() async {
developer.log('Alarm fired!');
// Get the previous cached count and increment it.
final prefs = await SharedPreferences.getInstance();
final currentCount = prefs.getInt(countKey) ?? 0;
await prefs.setInt(countKey, currentCount + 1);

// This will be null if we're running in the background.
uiSendPort ??= IsolateNameServer.lookupPortByName(isolateName);

Check failure on line 88 in packages/android_alarm_manager_plus/example/lib/main.dart

View workflow job for this annotation

GitHub Actions / Dart Analyzer

Undefined name 'IsolateNameServer'.

Try correcting the name to one that is defined, or defining the name. See https://dart.dev/diagnostics/undefined_identifier to learn more about this problem.
uiSendPort?.send(null);
}

Future<void> _requestPermission() async {
await Permission.scheduleExactAlarm
.onGrantedCallback(() => setState(() => _exactAlarmPermissionStatus = PermissionStatus.granted))
.request();
}

Future<void> _scheduleAlarm() async {
await AndroidAlarmManager.oneShot(
const Duration(seconds: 5),
Random().nextInt(1 << 31),
callback,
exact: true,
wakeup: true,
);
}

@override
Widget build(BuildContext context) {
final textStyle = Theme.of(context).textTheme.headlineMedium;
return Scaffold(
appBar: AppBar(
title: const Text('Android alarm manager plus example'),
elevation: 4,
),
appBar: AppBar(title: const Text('Android Alarm Manager Example')),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Spacer(),
Text(
'Alarms fired during this run of the app: $_counter',
style: textStyle,
textAlign: TextAlign.center,
),
Text('Alarms fired during this run: $_counter', style: textStyle, textAlign: TextAlign.center),
const SizedBox(height: 16),
Text('Total alarms fired: ${prefs.getInt(countKey)}', style: textStyle, textAlign: TextAlign.center),
const Spacer(),
Text(
'Total alarms fired since app installation: ${prefs?.getInt(countKey).toString() ?? ''}',
style: textStyle,
_exactAlarmPermissionStatus.isDenied
? 'Exact alarm permission denied. Alarms not available.'
: 'Exact alarm permission granted. Alarms available.',
textAlign: TextAlign.center,
),
const Spacer(),
if (_exactAlarmPermissionStatus.isDenied)
Text(
'SCHEDULE_EXACT_ALARM is denied\n\nAlarms scheduling is not available',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
)
else
Text(
'SCHEDULE_EXACT_ALARM is granted\n\nAlarms scheduling is available',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 32),
ElevatedButton(
onPressed: _exactAlarmPermissionStatus.isDenied
? () async {
await Permission.scheduleExactAlarm
.onGrantedCallback(() => setState(() {
_exactAlarmPermissionStatus =
PermissionStatus.granted;
}))
.request();
}
: null,
onPressed: _exactAlarmPermissionStatus.isDenied ? _requestPermission : null,
child: const Text('Request exact alarm permission'),
),
const SizedBox(height: 32),
ElevatedButton(
onPressed: _exactAlarmPermissionStatus.isGranted
? () async {
await AndroidAlarmManager.oneShot(
const Duration(seconds: 5),
// Ensure we have a unique alarm ID.
Random().nextInt(pow(2, 31) as int),
callback,
exact: true,
wakeup: true,
);
}
: null,
onPressed: _exactAlarmPermissionStatus.isGranted ? _scheduleAlarm : null,
child: const Text('Schedule OneShot Alarm'),
),
const Spacer(),
Expand Down
Loading