I need help regarding the images in my app. I would like to add 3 buttons for:
Download
Save as
Change phone wallpaper
I'm not using urls. I already have my images in an assets repository.
Do you have any idea how I can do that? Thank you.
You can copy paste run full code below
You can use package https://pub.dev/packages/wallpaper_manager
You can directly set wallpaper with image in assets
Example code's assets image path is "assets/tmp1.jpg"
code snippet
result = await WallpaperManager.setWallpaperFromAsset(
assetPath, WallpaperManager.HOME_SCREEN);
working demo
full code
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:wallpaper_manager/wallpaper_manager.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
String _wallpaperFile = 'Unknown';
String _wallpaperAsset = 'Unknown';
#override
void initState() {
super.initState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await WallpaperManager.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> setWallpaperFromFile() async {
setState(() {
_wallpaperFile = "Loading";
});
String result;
var file = await DefaultCacheManager().getSingleFile(
'https://images.unsplash.com/photo-1542435503-956c469947f6');
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await WallpaperManager.setWallpaperFromFile(
file.path, WallpaperManager.HOME_SCREEN);
} on PlatformException {
result = 'Failed to get wallpaper.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_wallpaperFile = result;
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> setWallpaperFromAsset() async {
setState(() {
_wallpaperAsset = "Loading";
});
String result;
String assetPath = "assets/tmp1.jpg";
// Platform messages may fail, so we use a try/catch PlatformException.
try {
result = await WallpaperManager.setWallpaperFromAsset(
assetPath, WallpaperManager.HOME_SCREEN);
} on PlatformException {
result = 'Failed to get wallpaper.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_wallpaperAsset = result;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: <Widget>[
RaisedButton(
child: Text("Platform Version"),
onPressed: initPlatformState,
),
Center(
child: Text('Running on: $_platformVersion\n'),
),
RaisedButton(
child: Text("Set wallpaper from file"),
onPressed: setWallpaperFromFile,
),
Center(
child: Text('Wallpaper status: $_wallpaperFile\n'),
),
RaisedButton(
child: Text("Set wallpaper from asset"),
onPressed: setWallpaperFromAsset,
),
Center(
child: Text('Wallpaper status: $_wallpaperAsset\n'),
),
],
)),
);
}
}
Related
I'd like to show some debug info in my App (e. g. user pressed Button A) and was thinking of using the TextField widget for this.
Using below code, I can record ambient sound from my phone and I'd like to add a widget at the bottom that displays timestamps of when the recordings started and stopped, including length of the recording. The idea is to use a ring buffer (package:circular_buffer) that keeps track of a pre-defined number of text lines being displayed in the TextField. Whenever something happens, the new debug info is added as an element to the ring buffer and the TextField is updated. I am very new to flutter, so I'm completely unsure how to achieve this. I was trying to use setState() but I don't know how to call it from other widgets. Is there a way to register as listener to state changes of other widgets and update the text accordingly?
import 'dart:async';
import 'dart:io';
// locale, datetime formatting
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:record/record.dart';
import 'package:path_provider/path_provider.dart';
// local imports
import './display_timer.dart';
void main() {
runApp(myApp());
}
class myApp extends StatefulWidget {
#override
myAppState createState() => myAppState();
}
class myAppState extends State<myApp> {
final record = Record();
bool bPressed = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Record',
home: Scaffold(
appBar: AppBar(
title: const Text('Record'),
),
body: Center(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: [
ElevatedButton(
child: bPressed ? const Text("Stop") : const Text("Record"),
onPressed: () {
setState(() {
bPressed = !bPressed;
});
action();
},
),
if (bPressed)
ElapsedTime(timestamp: DateTime.now().toString())
else
const Text("")
]),
),
));
}
String getTimestampSec() {
DateTime now = DateTime.now();
var dateString = DateFormat('yyyyMMdd_hhmmss').format(now);
return dateString;
}
Future<void> action() async {
// Get the state of the recorder
bool isRecording = await record.isRecording();
// Check and request permission
if (await record.hasPermission()) {
if (isRecording) {
// Stop recording
await record.stop();
} else {
// get write dir
// TODO: add fnc so dir only has to be initialize once
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
String outFile =
"$appDocPath/${getTimestampSec()}_ambient_test.m4a";
print("saving audio to: $outFile");
// Start recording
await record.start(
path: outFile,
encoder: AudioEncoder.aacLc, // by default
bitRate: 128000, // by default
samplingRate: 44100, // by default
);
}
}
print('Pressed');
}
}
To use setState() every time is not good practice rather than you can use ValueNotifier. Every time you update the string value it notify to your TextField and it will update TextField data.
ValueNotifier<String> logText = ValueNotifier<String>("Welcome");
ValueListenableBuilder(
valueListenable: logText,
builder: (context, logTextUpdate,child) {
return Text(
"${logText.value}",
style: TextStyle(fontSize: 25),
);
}),
when you want to update your text, assign value to logText
logText.value = "Happy to see you!"
I am using telephony dependencies for receive_sms.
It is working fine in the emulator and I receive every message sent, but it is not working on a real hardware phone.
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:telephony/telephony.dart';
onBackgroundMessage(SmsMessage message) {
debugPrint("onBackgroundMessage called");
}
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _message = "";
final telephony = Telephony.instance;
#override
void initState() {
super.initState();
initPlatformState();
}
onMessage(SmsMessage message) async {
setState(() {
_message = message.body ?? "Error reading message body.";
});
}
onSendStatus(SendStatus status) {
setState(() {
_message = status == SendStatus.SENT ? "sent" : "delivered";
});
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
// Platform messages may fail, so we use a try/catch PlatformException.
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
final bool? result = await telephony.requestPhoneAndSmsPermissions;
if (result != null && result) {
telephony.listenIncomingSms(
onNewMessage: onMessage, onBackgroundMessage: onBackgroundMessage);
}
if (!mounted) return;
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child: Text("Latest received SMS: $_message")),
TextButton(
onPressed: () async {
await telephony.openDialer("123413453");
},
child: Text('Open Dialer'))
],
),
));
}
}
I made sure the correct permissions are added in the Android Manifest file. I asked for the RECEIVE_SMS and BROADCAST_SMS permissions and it appears to be working since I can receive messages in the emulator.
What am I doing wrong?
Try asking for permission before you start listening to the message.
bool permissionsGranted = await telephony.requestPhoneAndSmsPermissions;
here are listed permission required and how to ask.
https://telephony.shounakmulay.dev/permissions
Make sure you added these permission in manifest.
<manifest>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application>
...
...
<receiver android:name="com.shounakmulay.telephony.sms.IncomingSmsReceiver"
android:permission="android.permission.BROADCAST_SMS" android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
</application>
</manifest>
I am using "mobile_number(version - 1.0.3)" plugin to get mobile number in flutter app, am running in original device but i couldn't get mobile number.instead of errors i can get mobile number as null along with other sim details as shown in screen shot.
help me to resolve this problem, i had just copy pasted the example given by plugin that is the code
plugin link
It says:
Note: If the mobile number is not pre-exist on sim card it will not return te phone number.
I think mobile number does not pre-exist on the SIM if the SIM is not original (i.e. replaced)
If the phone number isn't stored on the sim (aka null), then you can't get it from anywhere else, in that case you probably want to forward the user to a different page where they can type the phone number using TextField and then store it somewhere
Use Mobile_number package to get mobile number and other details. For example
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mobile_number/mobile_number.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _mobileNumber = '';
List<SimCard> _simCard = <SimCard>[];
#override
void initState() {
super.initState();
MobileNumber.listenPhonePermission((isPermissionGranted) {
if (isPermissionGranted) {
initMobileNumberState();
} else {}
});
initMobileNumberState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initMobileNumberState() async {
if (!await MobileNumber.hasPhonePermission) {
await MobileNumber.requestPhonePermission;
return;
}
String mobileNumber = '';
// Platform messages may fail, so we use a try/catch PlatformException.
try {
mobileNumber = (await MobileNumber.mobileNumber)!;
_simCard = (await MobileNumber.getSimCards)!;
} on PlatformException catch (e) {
debugPrint("Failed to get mobile number because of '${e.message}'");
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_mobileNumber = mobileNumber;
});
}
Widget fillCards() {
List<Widget> widgets = _simCard
.map((SimCard sim) => Text(
'Sim Card Number: (${sim.countryPhonePrefix}) - ${sim.number}\nCarrier Name: ${sim.carrierName}\nCountry Iso: ${sim.countryIso}\nDisplay Name: ${sim.displayName}\nSim Slot Index: ${sim.slotIndex}\n\n'))
.toList();
return Column(children: widgets);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
children: <Widget>[
Text('Running on: $_mobileNumber\n'),
fillCards()
],
),
),
),
);
}
}
I'm trying to develop "BLE Control App" with using flutter_Blue.
I added a tab bar so I want to Maintain Bluetooth State "Connect".
so I'm trying to use Provider, To set connection state but I have an error like this.
**======== Exception caught by foundation library ====================================================
The following assertion was thrown while dispatching notifications for BluetoothProvider:
setState() or markNeedsBuild() called during build.
This _InheritedProviderScope<BluetoothProvider> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: _InheritedProviderScope<BluetoothProvider>
value: Instance of 'BluetoothProvider'
listening to value
The widget which was currently being built when the offending call was made was: Consumer<BluetoothProvider>
dirty
dependencies: [_InheritedProviderScope<BluetoothProvider>]
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4138:11)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4153:6)
#2 _InheritedProviderScopeElement.markNeedsNotifyDependents (package:provider/src/inherited_provider.dart:531:5)
#3 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:243:25)
#4 BluetoothProvider.startScan (package:flutter_joystick/provider/bluetooth_provider.dart:46:5)
...
The BluetoothProvider sending notification was: Instance of 'BluetoothProvider'**
this is my bluetooth provider code
class BluetoothProvider with ChangeNotifier{
final String SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
final String CHARACTERISTIC_UUID="0000ffe1-0000-1000-8000-00805f9b34fb";
final String TARGET_DEVICE_NAME="HMSoft";
FlutterBlue flutterBlue = FlutterBlue.instance;
StreamSubscription<ScanResult> scanSubScription;
BluetoothDevice targetDevice;
BluetoothCharacteristic targetCharacteristic;
BluetoothState bluetoothState;
String connectionText="";
String joystick="";
startScan(){
connectionText="Start Scanning";
scanSubScription = flutterBlue.scan().listen((scanResult){
if(scanResult.device.name==TARGET_DEVICE_NAME){
print("Device Found");
stopScan();
connectionText="Found Target Device";
targetDevice = scanResult.device;
}
}, onDone: () => stopScan());
notifyListeners();
}
stopScan(){
scanSubScription?.cancel();
scanSubScription=null;
notifyListeners();
}
connectToDevice() async{
if(targetDevice==null) return;
connectionText = "Device Connecting";
await targetDevice.connect();
print("Device Connected");
connectionText="Device Connected";
discoverServices();
notifyListeners();
}
disconnectFromDevice(){
if(targetDevice==null) return;
targetDevice.disconnect();
connectionText="Device Disconnected";
notifyListeners();
}
discoverServices() async{
if(targetDevice==null) return;
List<BluetoothService> services = await targetDevice.discoverServices();
services.forEach((service) {
if(service.uuid.toString() == SERVICE_UUID){
service.characteristics.forEach((characteristc) {
if (characteristc.uuid.toString() == CHARACTERISTIC_UUID) {
targetCharacteristic = characteristc;
writeData("Connect Complete!\r\n");
connectionText = "All Ready with ${targetDevice.name}";
}
});
}
}
);
notifyListeners();
}
writeData(String data) async{
if(targetCharacteristic==null) return;
List<int> bytes = utf8.encode(data);
await targetCharacteristic.write(bytes);
notifyListeners();
}
}
Funny, the Bluetooth connection is progressing, but the error written above keeps coming up through the console window.
The first page of the Tab Bar is the joystick page, and Bluetooth is connected due to an error, but the joystick is not working.
Here is Joystick code
class JoyPad extends StatefulWidget {
#override
_JoyPadState createState() => _JoyPadState();
}
class _JoyPadState extends State<JoyPad> {
BluetoothProvider _bluetoothProvider;
#override
Widget build(BuildContext context) {
_bluetoothProvider = Provider.of<BluetoothProvider>(context,listen:false);
return Consumer<BluetoothProvider>(
builder:(context,provider,child) {
_bluetoothProvider.startScan();
return Scaffold(
appBar: AppBar(
title: Text(_bluetoothProvider.connectionText),
backgroundColor: Colors.indigoAccent,
actions: <Widget>[
IconButton(
icon: Icon(Icons.bluetooth), iconSize: 30,
onPressed: () {
_bluetoothProvider.connectToDevice();
print(_bluetoothProvider.bluetoothState.toString());
},
),
IconButton(
icon: Icon(Icons.bluetooth_disabled), iconSize: 30,
onPressed: () {
_bluetoothProvider.disconnectFromDevice();
print(_bluetoothProvider.bluetoothState.toString());
}),
],
),
body: joystickWidget(),
);
});
}
}
Additionally, the provider does not "setState" so I try to display connection text according to the status change on the App Bar, but it is not possible.
I would also appreciate it if you could tell me how to solve it.
You are actually encountering this error because you try to rebuild the widget tree while it's being build.
Your call on _bluetoothProvider.startScan();in your Consumer's builder method will call the notifyListeners method which actually tries to rebuild the tree while it's being build, thus that exception will be thrown.
WHY?
The Consumer widget is actually listening to changes on your BluetoothProvider; so when you call the notifyListeners on the BluetothProvider class, the Consumer tries to rebuild itself, which is not authorized.
A solution would be to first build the tree, and then call the startScan method.
You could try this:
Provider Code
class BluetoothProvider with ChangeNotifier{
final String SERVICE_UUID = "0000ffe0-0000-1000-8000-00805f9b34fb";
final String CHARACTERISTIC_UUID="0000ffe1-0000-1000-8000-00805f9b34fb";
final String TARGET_DEVICE_NAME="HMSoft";
FlutterBlue flutterBlue = FlutterBlue.instance;
StreamSubscription<ScanResult> scanSubScription;
BluetoothDevice targetDevice;
BluetoothCharacteristic targetCharacteristic;
BluetoothState bluetoothState;
String connectionText="";
String joystick="";
startScan() {
connectionText="Start Scanning";
scanSubScription = flutterBlue.scan().listen((scanResult){
if(scanResult.device.name==TARGET_DEVICE_NAME){
print("Device Found");
stopScan();
connectionText="Found Target Device";
targetDevice = scanResult.device;
}
}, onDone: () => stopScan());
notifyListeners();
}
stopScan() {
scanSubScription?.cancel();
scanSubScription=null;
notifyListeners();
}
connectToDevice() async{
if(targetDevice==null) return;
connectionText = "Device Connecting";
await targetDevice.connect();
print("Device Connected");
connectionText="Device Connected";
discoverServices();
notifyListeners();
}
disconnectFromDevice(){
if(targetDevice==null) return;
targetDevice.disconnect();
connectionText="Device Disconnected";
notifyListeners();
}
discoverServices() async {
if(targetDevice==null) return;
List<BluetoothService> services = await targetDevice.discoverServices();
services.forEach((service) {
if(service.uuid.toString() == SERVICE_UUID){
service.characteristics.forEach((characteristc) {
if (characteristc.uuid.toString() == CHARACTERISTIC_UUID) {
targetCharacteristic = characteristc;
writeData("Connect Complete!\r\n");
connectionText = "All Ready with ${targetDevice.name}";
}
});
}
});
notifyListeners();
}
writeData(String data) async{
if(targetCharacteristic==null) return;
List<int> bytes = utf8.encode(data);
await targetCharacteristic.write(bytes);
notifyListeners();
}
}
Widget code
class JoyPad extends StatefulWidget {
#override
_JoyPadState createState() => _JoyPadState();
}
class _JoyPadState extends State<JoyPad> {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
// The code in this block will be executed after the build method
context.read<BluetoothProvider>().startScan();
});
}
#override
Widget build(BuildContext context) {
return Consumer<BluetoothProvider>(
builder:(context,provider,child) {
return Scaffold(
appBar: AppBar(
title: Text(_bluetoothProvider.connectionText),
backgroundColor: Colors.indigoAccent,
actions: <Widget>[
IconButton(
icon: Icon(Icons.bluetooth), iconSize: 30,
onPressed: () {
_bluetoothProvider.connectToDevice();
print(_bluetoothProvider.bluetoothState.toString());
},
),
IconButton(
icon: Icon(Icons.bluetooth_disabled), iconSize: 30,
onPressed: () {
_bluetoothProvider.disconnectFromDevice();
print(_bluetoothProvider.bluetoothState.toString());
},
),
],
),
body: joystickWidget(),
);
});
}
}
}
context.read<BluetoothProvider>().startScan(); is a shortcut for Provider.of<BluetoothProvider>(context, listen: false).startScan() : it basically does the same thing.
So am trying to use google pay in my flutter application and below is my code. When I run the application is shows google pay dialog with my google pay email and card details and an error "Unrecognised app. Please make sure that you trust this app before proceeding. When I press the "Continue" button I get "Request failed" "Unexpected developer error, please try again later" Please what am I doing wrong?
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:google_pay/google_pay.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
String _googlePayToken = 'Unknown';
#override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await GooglePay.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
await GooglePay.initializeGooglePay("my google play base64EncodedPublicKey");
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
children: <Widget>[
Text('Running on: $_platformVersion\n'),
Text('Google pay token: $_googlePayToken\n'),
FlatButton(
child: Text("Google Pay Button"),
onPressed: onButtonPressed,
)
]
),
),
),
);
}
void onButtonPressed() async{
setState((){_googlePayToken = "Fetching";});
try {
await GooglePay.openGooglePaySetup(
price: "10.0",
onGooglePaySuccess: onSuccess,
onGooglePayFailure: onFailure,
onGooglePayCanceled: onCancelled);
setState((){_googlePayToken = "Done Fetching";});
} on PlatformException catch (ex) {
setState((){_googlePayToken = "Failed Fetching";});
}
}
void onSuccess(String token){
setState((){_googlePayToken = token;});
}
void onFailure(){
setState((){_googlePayToken = "Failure";});
}
void onCancelled(){
setState((){_googlePayToken = "Cancelled";});
}
} ```
When I run the application is shows google pay dialog with my google pay email and card details and an error "Unrecognised app. Please make sure that you trust this app before proceeding. When I press the "Continue" button I get "Request failed" "Unexpected developer error, please try again later" Please what am I doing wrong?