Problem with Hive while saving the information - flutter

Wanna make function which will save the information after clicking the buttom (Save)
But Hive gives error...Screen of VS
Error is in this line:
static Box notes = Hive.box(HiveKeys.notesKey);
Exception has occurred.
HiveError (HiveError: The box "notes" is already open and of type Box.)

First of all you can not directly type hive data into a specific model. You need to get data from the box as dynamic and then cast that data to desired type, and the second thing is it seems that you have already opened this box somewhere in your code. It would be nice if you can share the code where you have opened hive box

If you want to store data in list form then please follow below step
Step 1: put in main.dart file
await Hive.openBox<List>("hiveTable");
Step 2: make a model class that contains the adapter of the hive
part 'hive_clean_entity.freezed.dart';
part 'hive_clean_entity.g.dart';
#freezed
#HiveType(typeId: 6, adapterName: "ContactCleanHiveAdapter")
#freezed
class HiveCleanEntity with _$HiveCleanEntity {
const factory HiveCleanEntity({
#HiveField(0) #Default("") String contactId,
#HiveField(1) #Default("") String displayName,
#HiveField(2) #Default("") String givenName,
#HiveField(3) #Default("") String phoneNumber,
}) = _HiveCleanEntity;
factory HiveCleanEntity.initial() => const HiveCleanEntity(
contactId: "",
displayName: "",
givenName: "",
phoneNumber: "",
);
}
like this - you can pass typeId of your choice
Step 3: run the build_runner command so they generate 2 file of model dto
flutter pub run build_runner watch --delete-conflicting-outputs
Step 4: Now open box where you want to store data :
ListHiveCleanEntity putlist = [];
HiveCleanEntity hiveCleanEntity =
HiveCleanEntity(
contactId: “1”,
displayName: "2",
givenName: "xyz",
phoneNumber:”+91”);
putlist.add(hiveCleanEntity);
final cleanContactBox = Hive.box<List>("hiveTable");
cleanContactBox.put("subTable",putlist);
Step 5: getting data into local storage
final list = cleanContactBox.get("subTable")?.cast<HiveCleanEntity>() ?? [];

Related

How to use a feedback from API

so im calling an API with some JSON feedback like so :
[{"student_name" : "Raskal", "student_classes" : "XII"}]
I call this using this format :
Future< StudentInfo > _studentCard() async {
var data = await MainApi("meKTA", 'getEKTA', '', "getEKTA");
var jsonData = json.decode(data);
var jsonParse = jsonData[0];
final StudentInfo studentinfo = StudentInfo(
jsonParse['student_name'],
jsonParse['student_classes'],
);
print(data);
return studentinfo;
}
class StudentInfo {
final String student_name;
final String student_classes;
StudentInfo(
this. student_name,
this. student_classes,
);
}
I tried to call the API feedback like this
Text(snapshot.data.student_name)
but i get an error on the student_name
the result i want is that the TEXT shows Raskal
Error I got
The property 'student_name' can't be unconditionally accessed because the receiver can be 'null'.
on SDK : ">=2.11.0 <3.0.0", Ive got no problem on calling like that, but on sdk: ">=2.12.0 <3.0.0" ive got that problem
Since SDK 2.12. Flutter using Sound null safety. You have to migrate all of your code to run your app correctly. See more: Sound null safety
Try to check null before passing data into Text.
The simplest way you can do it like this one:
Text(snapshot.data?.student_name ? '')

why can't create user using stream chat api in flutter?

I'm trying to create a chat screen in my flutter application using Stream chat API. the problem is when I try to create a channel with two users it shows that the users are not created even though I have created them:
E/flutter ( 4695): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception:
StreamChatNetworkError(code: 4, message: GetOrCreateChannel failed with error: "The following
users are involved in channel create operation, but don't exist: [hasan11 mohammed11]. Please
create the user objects before setting up the channel.", statusCode: 400, data:
ErrorResponse(code: 4, message: GetOrCreateChannel failed with error: "The following users are
involved in channel create operation, but don't exist: [hasan11 mohammed11]. Please create the
user objects before setting up the channel.", statusCode: 400, moreInfo:
https://getstream.io/chat/docs/api_errors_response))
here is my dart code for initializing the channel and the users:
onPressed () {
await streamAPI.initUser(client,
username: 'hasan',
id: Config.hasanID,
token: Config.hasanToken);
final channel = await streamAPI.createChannel(
client, 'messaging', 'sample', [Config.hasanID, Config.mohammedID]);
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) =>
chat(client: client, channel: channel)));
}
StreamAPI.dart code:
import 'package:flutter/cupertino.dart';
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
class streamAPI {
static Future initUser(
StreamChatClient client, {
#required String username,
#required String id,
#required String token
}) async {
final user = User(
id: id,
extraData: {
'name': username
}
);
await client.connectUser(user, token);
}
static Future<Channel> createChannel(
StreamChatClient client,
#required String type,
#required String id,
List<String> idMembers
) async {
final channel = client.channel(type, id: id, extraData: {
'name': 'channel1',
'members': idMembers
});
await channel.create();
channel.watch();
return channel;
}
}
Can anyone help me please?
Make sure that these users are created on the Stream backend. In your Stream dashboard, go to the Explorer -> users section, and you should see a list of all your users. Ensure the IDs match what you have in your code.
Stream Dashboard Example
Take note you don't need to call both create and watch, as watch will automatically create the channel.
If you're using the Stream Chat UI or Core components, you don't even need to call watch yourself, then you only need to call create.
I recommend taking a look at the Flutter tutorial page if you're still stuck: https://getstream.io/chat/flutter/tutorial/
Or the Stream Flutter YouTube Playlist: https://www.youtube.com/watch?v=pO_MOJRqYlk&list=PLNBhvhkAJG6t-BxkRAnSqa67lm5C1mpKk

how to solve dynamic list type casting error in Hive?

sorry I am new in using Flutter and using Hive local storage.
I am using
hive: ^2.0.4
hive_flutter: ^1.0.0
I open the box in main function like this
Future<void> main() async {
await Hive.initFlutter();
await Hive.openBox<List<Event>>("events");
}
after getting the data from the server, I save all the events to hive by using code like this
final eventsBox = Hive.box<List<Event>>("events");
final List<Event> eventsFromServer = await getEventsFromServer();
eventsBox.put("recommended_events", eventsFromServer);
but I have error when trying to read the data from the box, I read it like this
final eventsBox = Hive.box<List<Event>>("events");
// error in this one line below
final eventsFromHive = eventsBox.get("recommended_events", defaultValue: []) ?? [];
type 'List < dynamic > ' is not a subtype of type 'List< Event >?' in type
cast
how to solve this type casting error?
from the documentation in here it is said
Lists returned by get() are always of type List (Maps of type
Map<dynamic, dynamic>). Use list.cast() to cast them to a
specific type.
I don't know if it is the solution of my problem or not, but I don't know how to implement that in my code.
I tried it like this, but I still have the same error
final eventsFromHive = eventsBox.get("recommended_events")!.cast<Event>();
or maybe the way I write the syntax to save and read the list are totally wrong? please help :)
Is not necessary to open your box as a List, because it is a box and can store many objects of the type that you declare, for example:
await Hive.openBox<MyModel>(boxName);
To get all the objects or data stored in that box, you can query like this:
final box = Hive.box<CompanyModel>(boxName);
List<CompanyModel> interviews = box.values.toList();
In addition, you have to create an Adapter Model if you want to store your own Model with Hive.
There is two dev dependencies to auto generate the Model:
dev_dependencies:
hive_generator:
build_runner:
Importing that dependencies and running this command flutter packages pub run build_runner build will generate the Model, but also you have to create your Model as the documentation indicates.
I suggest you to check out the documentation.
Hive - Generate Adapter
I can finally solve it by using it like this. in main function
Future<void> main() async {
await Hive.initFlutter();
await Hive.openBox("events");
}
when saving data list
final eventsBox = Hive.box("events");
eventsBox.put("recommended_events", eventsFromServer);
and read it like this
final eventsBox = Hive.box("events");
final eventsFromHive = eventsBox.get("recommended_events")?.cast<Event>() ?? [];
I have faced this kind of problem. It was absolutely the same. I do not know how you got kinda problem. Maybe it was the same with mine. I have just cleaned the box. and it has worked on me.
**Cause: **
I started it immediately after I made the box (for testing). he had taken the List<dynamic> object as it store. Once I made it clear, it stocked up data I had just given and it worked
Try:
boxName.clear() inside initState() and re-run it. if it will work do not forget to delete the line!
if you forget, it will clear the box every time.
Done with getting Hive as an List Object :)
Future<List<CustomModel>> getModels() async {
//box = await Hive.openBox<CustomModel>(Constants.Hive);
return box?.values.toList(growable: false)?.cast<CustomModel>() ?? <CustomModel>[];
}

Flutter dart export hive saved data to file to retrieve later

I am developing a barcode app and save the data to hive. What I need to know is there a way to export the saved hive database to a backup file and be able to retrieve it for instance if the app crashed or your phone is lost. This is for blind accessibility. Want to export the data to a file that I can save to my pc to store and if something happens I do not have to scan all the products again to build the database. If hive can not do this can someone point me in a direction of which flutter dart database can do this. Thank you
Ok the answer did not work for me. Here is a copy of my model file
import 'package:hive/hive.dart';
part 'product.g.dart';
#HiveType(typeId: 0)
class Product extends HiveObject{
#HiveField(0)
String itemName;
#HiveField(1)
String barCode;
#HiveField(2)
String bcType;
Product(this.itemName, this.barCode, this.bcType);
}
Then I call my box like
var box = Hive.box('products');
How to encode this to json for saving?
I use the next
Future<File> _createBackupFile() async {
/// This example uses the OS temp directory
File backupFile = File('${Directory.systemTemp.path}/backup_barcode.json');
try {
/// barcodeBox is the [Box] object from the Hive package, usually exposed inside a [ValueListenableBuilder] or via [Hive.box()]
var barcodeBox = Hive.box<Product>('products');
backupFile = await backupFile.writeAsString(jsonEncode(barcodeBox.values));
return backupFile;
} catch (e) {
// TODO: handle exception
print(e);
}
}
There is not a "out-of-the-box" solution for that as far as I know. It depends a lot on your use case of how you want to do that (since there are many ways). For a complete example of how I did that for my app, you can take a look here:
https://github.com/Kounex/obs_blade/blob/master/lib/views/settings/logs/log_detail/log_detail.dart (I made use of the share package in order to easily export it - but that's not necessary)
Flutter also has its own documentation on reading and writing files (https://flutter.dev/docs/cookbook/persistence/reading-writing-files) - I will add some information to round it up:
Storage location
First of all we have to think about where to store the "backup file". Flutter exposes common paths on its own which you can make use of (additionally the path_provider package gives you more flexibility). If you want this backup file to be temporarily, you can for example use:
Directory.systemTemp;
The documentation states: "This is the directory provided by the operating system for creating temporary files and directories in." The OS will make sure to delete them in different occasions so you don't have to worry about it. You can also create additional directories inside this temp directory to make it more distinguishable, like:
Directory.systemTemp.createTemp('my_app');
IMPORTANT: this applies to non-sensitive data. If whatever you are processing contains sensitive data (like names, addresses etc.), you have to ensure data security / data privacy. In such cases I would make use of the path_provider package as mentioned earlier and create those files in the documents directory (getApplicationDocumentsDirectory()) and make sure they are deleted immediately after usage / export. Even encrypting the content may be a good idea - but I'm not diving into this here.
File mangagement
Once we know where to store the file, we just need to create them. Chapter 3 and 4 of the flutter documentation earlier exactly states how to do that, so I'm rather focusing on what to write.
A common and very convenient way to compose your data is JSON. Flutter also has documentation for that: https://flutter.dev/docs/development/data-and-backend/json
Since you are using Hive, you probably already have classes representing entries in your boxes and you could easily just add the toJson() function where you return a Map<String, dynamic> (as seen in the documentation) and you can use that to finally write the needed information into a file.
Based on your Hive class, this is how to adjust it in otder to serialize it correctly:
import 'package:hive/hive.dart';
part 'product.g.dart';
#HiveType(typeId: 0)
class Product extends HiveObject{
#HiveField(0)
String itemName;
#HiveField(1)
String barCode;
#HiveField(2)
String bcType;
Product(this.itemName, this.barCode, this.bcType);
/// This function will automatically be used by the [jsonEncode()] function internally
Map<String, dynamic> toJson() => {
'itemName': this.itemName,
'barCode': this.barCode,
'bcType': this.bcType,
}
}
A small example implementation could look like this:
Future<File?> _createBackupFile() async {
/// This example uses the OS temp directory
File backupFile = File('${Directory.systemTemp.path}/backup_barcode.json');
try {
/// barcodeBox is the [Box] object from the Hive package, usually exposed inside a [ValueListenableBuilder] or via [Hive.box()]
backupFile = await backupFile.writeAsString(jsonEncode(barcodeBox.values));
return backupFile;
} catch (e) {
// TODO: handle exception
}
}
This will save the JSON representation of your Hive box inside the temporary OS directory. You can swap the directory with whatever suits you best (on Android for example on the external storage for easier accessibility).
Now you have to think about how and when to trigger this. You can do this manually by triggering a button press for example or automatically after a certain action (like adding a new barcode) and choose a way that works for you to access the file. As stated earlier, saving the file somewhere easily accessible like the external storage on Android or making use of the share package are possible solutions.
Android Manifest should contain these:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:requestLegacyExternalStorage="true"
You will need this package and this package to proceed.
Now a method to backup the data to a desired location:
Future<void> createBackup() async {
if (Hive.box<Product>('products').isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('No Products Stored.')),
);
return;
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Creating backup...')),
);
Map<String, dynamic> map = Hive.box<Product>('products')
.toMap()
.map((key, value) => MapEntry(key.toString(), value));
String json = jsonEncode(map);
await Permission.storage.request();
Directory dir = await _getDirectory();
String formattedDate = DateTime.now()
.toString()
.replaceAll('.', '-')
.replaceAll(' ', '-')
.replaceAll(':', '-');
String path = '${dir.path}$formattedDate.json';//Change .json to your desired file format(like .barbackup or .hive).
File backupFile = File(path);
await backupFile.writeAsString(json);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Backup saved in folder Barcodes')),
);}
Future<Directory> _getDirectory() async {
const String pathExt = 'Barcodes/';//This is the name of the folder where the backup is stored
Directory newDirectory = Directory('/storage/emulated/0/' + pathExt);//Change this to any desired location where the folder will be created
if (await newDirectory.exists() == false) {
return newDirectory.create(recursive: true);
}
return newDirectory;
}
Finally, call this function using a button and it will save a backup with the current time as the name in JSON format.
createBackup()
After this to restore the data back to Hive,
Future<void> restoreBackup() async {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Restoring backup...')),
);
FilePickerResult? file = await FilePicker.platform.pickFiles(
type: FileType.any,
);
if (file != null) {
File files = File(file.files.single.path.toString());
Hive.box<Product>('products').clear();
Map<String, dynamic> map = jsonDecode(await files.readAsString());
for (var i = 0; i < map.length; i++) {
Product product = Product.fromJson(i.toString(), map);
Hive.box<Product>('products').add(product);
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Restored Successfully...')),
);
}
}
Finally, call this function using a button and it will open the file picker where you can select the backup file and it will remove the existing data and add every item from the backup in a loop.
restoreBackup()

App login with google account and firebase integration

I'm developping a crowfunding application with flutter.
The first step I've done (after firebase integration to my app) is the login page (login with google) and it works correctly.
In the firebase dashboard I can see the number of users logged and their activity, but I can't see their details (eg. their name, surname and google mail).
Is it possibile to track these data in firebase dashboard? If it is yes, how can I do it?
Thanks
To save other details, for example: name, age, gender.
First you need to create a Model for this User.
In the sign up process, you need to save this information using Firestore.
I will put below a code for example:
In the example, it is an Uber style app and I want to retrieve the user's name mainly and I want to know its type, whether it is a driver or a passenger.
Sign up Screen
I am using the form of registration only with email / password, but it makes no difference, after registering, see the code below, in the ".then", is where the data is passed to the Firestore
void cadastrarUser(Usuario usuario) {
FirebaseAuth auth = FirebaseAuth.instance;
FirebaseFirestore db = FirebaseFirestore.instance;
auth
.createUserWithEmailAndPassword(
email: usuario.email, password: usuario.senha)
.then((firebaseUser) {
db.collection("usuarios").doc(firebaseUser.user.uid).set(usuario.toMap());
switch (usuario.typeUser) {
case "motorista":
Get.toNamed("/painel-motorista");
break;
case "passageiro":
Get.toNamed("/painel-passageiro");
break;
}
}).catchError((error) {
errorMessage =
"Erro ao cadastrar usuário, verifique os campos e tente novamnte!";
});
This method receives a User instance, to transfer this data from the User instance, you need to convert this object into a "map".
In the model, you need create a method for this conversion, see the example below:
class Usuario {
String _idUser;
String _nome;
String _email;
String _senha;
String _typeUser;
Usuario();
String checkTypeUser(bool typeUser) {
return typeUser ? "motorista" : "passageiro";
}
Map<String, dynamic> toMap() {
Map<String, dynamic> map = {
"nome": this.nome,
"email": this.email,
"typeUser": this.typeUser
};
return map;
}