self_launcher 1.0.1
self_launcher: ^1.0.1 copied to clipboard
A lightweight Flutter package for bringing Android apps to the foreground. Simple method to reopen or bring your app to foreground when called.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:self_launcher/self_launcher.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Self Launcher Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Self Launcher Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isLoading = false;
String _message = '';
String _statusMessage = 'Ready to bring app to foreground';
int _launchCount = 0;
Future<void> _bringToForeground() async {
setState(() {
_isLoading = true;
_message = '';
_statusMessage = 'Attempting to bring app to foreground...';
});
try {
final success = await SelfLauncher.bringToForeground();
setState(() {
if (success) {
_launchCount++;
_message = 'App brought to foreground successfully!';
_statusMessage = 'Success! Launch count: $_launchCount';
} else {
_message = 'Failed to bring app to foreground';
_statusMessage = 'Failed - please try again';
}
});
} catch (e) {
setState(() {
_message = 'Error: $e';
_statusMessage = 'Error occurred - check logs';
});
} finally {
setState(() {
_isLoading = false;
});
}
}
Widget _buildStatusCard() {
return Card(
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Icon(
_launchCount > 0 ? Icons.check_circle : Icons.info,
size: 48,
color: _launchCount > 0 ? Colors.green : Colors.blue,
),
const SizedBox(height: 16),
Text(
_statusMessage,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
),
if (_launchCount > 0) ...[
const SizedBox(height: 8),
Text(
'Total launches: $_launchCount',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
),
],
],
),
),
);
}
Widget _buildInstructionsCard() {
return Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'How to Test',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
const Text(
'1. Tap "Bring to Foreground" button\n'
'2. Minimize the app (press home button)\n'
'3. Tap the button again to bring app back\n'
'4. Try closing the app completely and test again',
style: TextStyle(fontSize: 14),
),
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.blue[200]!),
),
child: Row(
children: [
Icon(Icons.info, color: Colors.blue[700], size: 20),
const SizedBox(width: 8),
const Expanded(
child: Text(
'No permissions required! This plugin uses standard Android intents.',
style: TextStyle(fontSize: 12),
),
),
],
),
),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
centerTitle: true,
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildStatusCard(),
const SizedBox(height: 24),
SizedBox(
height: 60,
child: ElevatedButton(
onPressed: _isLoading ? null : _bringToForeground,
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Colors.white,
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
child: _isLoading
? const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
SizedBox(width: 12),
Text('Processing...'),
],
)
: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.launch, size: 24),
SizedBox(width: 8),
Text(
'Bring to Foreground',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
],
),
),
),
if (_message.isNotEmpty) ...[
const SizedBox(height: 16),
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: _message.contains('Error') || _message.contains('Failed')
? Colors.red[50]
: Colors.green[50],
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: _message.contains('Error') || _message.contains('Failed')
? Colors.red[200]!
: Colors.green[200]!,
),
),
child: Row(
children: [
Icon(
_message.contains('Error') || _message.contains('Failed')
? Icons.error
: Icons.check_circle,
color: _message.contains('Error') || _message.contains('Failed')
? Colors.red[700]
: Colors.green[700],
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Text(
_message,
style: TextStyle(
color: _message.contains('Error') || _message.contains('Failed')
? Colors.red[700]
: Colors.green[700],
fontWeight: FontWeight.w500,
),
),
),
],
),
),
],
const SizedBox(height: 24),
_buildInstructionsCard(),
],
),
),
);
}
}