Null check operator error with tflite Flutter - flutter

The following code causes this error Null check operator used on a null value but I cannot figure out why.
import 'package:tflite_flutter/tflite_flutter.dart';
final modelFile = 'model.tflite';
void main() async {
foo();
}
void foo() async {
Interpreter inter = await Interpreter.fromAsset(modelFile);
}
The model exists at the correct location and I have tried multiple other locations just in case. The file is in my pubspec.yaml and I have tried multiple variations just in case. Not sure if I need to provide more parameters or something but I can't figure it out. Any help would be appreciated.
Just to test if it was an issue with me not placing the file in the correct location, or not referencing it in the pubspec.yaml I tested other assets such as Images and Text files in the same location and they loaded perfectly fine.

It looks like you have not exported the file. To fix to go to pubspec.yaml and find these lines:
flutter:
assets:
- model.tflite
And make sure you are specifying the correct file location when adding it through pubscpec. After that uninstall the app, do flutter clean, flutter pub get and it should work

I assumer the directory containing the model is named as "assets".
import 'package:tflite_flutter/tflite_flutter.dart';
final modelFile = 'assets/model.tflite';
void main() async {
foo();
}
void foo() async {
Interpreter inter = await Interpreter.fromAsset(modelFile);
}
Code for pubspec:-
flutter:
assets:
- assets/model.tflite

Related

Flutter can't seem to find a Json file from relative path

I apologise in advance if this is a silly question, but I have created a file and stored it in my "assets" sub-directory, which is at the same level as my lib directory and my pubspec.yaml file. I've set the relative path to "assets/ExerData.json" in my code (see below).
When I run the code saved as a scratch.dart file as shown below, hitched up to a Galaxy Nexus API 29 emulator, it can only tell me "Can't find file!"
import 'dart:io';
import 'package:flutter/services.dart';
String filePath = "assets/ExerData.json";
void main() {
performTasks();
}
void performTasks() {
if (checkFileExists(filePath)) {
readFile(filePath);
} else {
print("Can't find file");
}
}
bool checkFileExists(path) {
bool result = File(path).existsSync();
print(result.toString());
return result;
}
Future<String> readFile(path) async {
return await rootBundle.loadString(filePath);
}
I populated my pubspec.yaml file with this entry:
assets:
- assets/ExerData.json
I expected it to find my file, read it using rootbundle.loadstring(path), and print out the resulting string to the console.
As I say, all it did was print "Can't find file".
I'd very much appreciate you help on this one!
Thanks in advance!
The rootBundle contains the resources that were packaged with the app when it was built. All files specified under assets: in your pubspec are packaged with the app. You can check if file exists by wrapping rootBundle.loadString() inside try{} catch(){} block.
Future<bool> fileExists(String path) async {
try {
await rootBundle.loadString(path);
} catch (_) {
return false;
}
return true;
}
or
Future<String?> loadFile(String path) async {
try {
return await rootBundle.loadString(path);
} catch (_) {
// File not found Exception
return null;
}
}
File is a dart class. It needs absolute or relative path of the file being read.
You can use File with path_provider to get the absolute path from the current File System.
For example on Android:
Future<void> getPath() async {
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
print('PATH IS : $appDocPath');
}
prints
'/data/user/0/com.soliev.file_demo/app_flutter'
Use:
String data = await DefaultAssetBundle.of(context).loadString("assets/ExerData.json");
final jsonResult = jsonDecode(data);
Reference: How to load JSON assets into a Flutter App?
As it turns out, the program logic had not completed initializing the necessary binding.
I called the method WidgetsFlutterBinding.ensureInitialized() in the first line of the main class and everything started working as I expected.
Thanks to everyone who looked at my question!
Here's a similar question involving binding with XML files:
How to read XML files in flutter?

Getting learning_text_recognition library to work in Flutter

I'm trying to add the learning_text_recognition library to my Flutter project. I was able to get the example in the API docs to work with no problems (https://pub.dev/packages/learning_text_recognition/example), but now I'm trying to add it to my own project using the information found on the Readme tab of the same website. It's slightly different than how the example worked and I'm now receiving several errors that I didn't receive in the example. Specifically, the errors are on the following line:
RecognizedText result = await textRecognition.process(image);
It says that the await function can only be used in an async function, but I don't know if I should make the function or the class async? It also says that the method 'process isn't defined for the type 'TextRecognition', but I don't know what the method should be, since that part worked perfectly fine in the example. It was also complaining that image wasn't defined, but I just created a variable called image with InputCameraView, which seemed to work.
I've tried moving the code into a new function and made an image variable. This is what the code looks like now:
getInfo(){
var image = InputCameraView(
canSwitchMode: false,
mode: InputCameraMode.gallery,
title: 'Text Recognition',
onImage: (InputImage image) {
// now we can feed the input image into text recognition process
},
);
TextRecognition textRecognition = TextRecognition();
RecognizedText result = await textRecognition.process(image);
}
I've also included the following import statements:
import 'package:learning_input_image/learning_input_image.dart';
import 'package:learning_text_recognition/learning_text_recognition.dart';
import 'package:provider/provider.dart';
I'm not sure if I'm maybe missing a step?
Your function should have the async keyword to indicate that there will be wait points. See the dart async/await documentation.
Another detail for the example InputCameraView is a widget, it should not be inside the function. It must be using the onImage method of the InputCameraView to collect the recognition and the builder to build it. In the doc onImage calls the async function _startRecognition to collect the data you must do something in this line.
void getInfo() async {
var image = InputCameraView(
canSwitchMode: false,
mode: InputCameraMode.gallery,
title: 'Text Recognition',
onImage: (InputImage image) {
// now we can feed the input image into text recognition process
},
);
var textRecognition = TextRecognition();
var result = await textRecognition.process(image);
}

Flutter proper way to test dart:ui on Android device

I faced following problem:
My Android Flutter app has a serie of dart:ui calls, basically to do an application files backup. Lets just check how to test that it find the correct path of the app files. The function to test:
static Future<String> getUserPath() async {
final appDocDir = await getApplicationDocumentsDirectory();
final pathComponents = path.split(appDocDir.path);
pathComponents.removeLast();
final filepaths = path.join(path.joinAll(pathComponents), 'files', '.user');
if (!await Directory(filepaths).exists()) throw FileSystemException('User directory not found');
return filepaths;
}
Easy, it call different dart:ui functions to check where the user files are. It works now, but I want to write the test for this funcion. Basically I found two ways to test this is: using Flutter Drive tests to write integration tests, i followed this tutorial: https://flutter-website-staging.firebaseapp.com/testing/ . And using Flutter integration tests, using this guide: https://docs.flutter.dev/testing/integration-tests.
The test I wrote is next:
testWidgets('test_correct_path', (WidgetTester tester) async {
print('user folder: ' + await getUserPath());
assert('.user' == basename(await getUserPath()));
});
Using driver tests
I created the following folder on my project:
test_driver
├── backup.dart
└── backup_test.dart
On backup.dart
// This line imports the extension
import 'package:flutter_driver/driver_extension.dart';
import 'package:elRepoIo/main.dart' as app;
void main() {
// This line enables the extension
enableFlutterDriverExtension();
}
And on backup_test.dart I just added the needed functions after test main declaration:
void main() {
FlutterDriver driver;
// connect flutter driver to the app before executing the runs
setUpAll(() async {
driver = await FlutterDriver.connect();
});
// disconnect flutter driver from the app after executing the runs
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
// Tests down here
Then when I execute the tests using flutter drive --target=test_driver/backup.dart I receive a bunch of errors such flutter/packages/flutter_test/lib/src/frame_timing_summarizer.dart:5:8: Error: Not found: 'dart:ui' import 'dart:ui';
Using integration tests
Under
integration_test
├── backup_test.dart
I wrote the tests adding the following line:
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized(); // NEW
Then I run the test using flutter test integration_test/backup_test.dart -d $device_id where I get device_id using flutter devices.
If I debug this I found that the path is correct, but await Directory(filepaths).exists() is false.
It seem that if I run the app to create the folder and inmetially I run the tests the directory exist. Are integration tests deleting all file data? And how can I keep it?

Separate development from deployment assets in Flutter

I am using some assets during my development (fake API responses and random images), and for that, I am loading some assets.
Obviously I do not want those assets to be bundled with the release APK, how do you come around doing so?
For now, I have all assets in one pubspec.yaml.
The end goal is to be able to run the app flutter run and have fake backend. I know of mocking HTTP calls, but it is very difficult to wrap a full app, so now I have two different data source (one from assets and another http-based), and I call the one depending on kReleaseMode value.
Thanks!
I had the same problem (which also seems to be an orphaned flutter issue), but solved it using a Builder running in the dart build_runner - not to be confused with the flutter Builder pattern for widgets (which spoils the search results). This works as sketched here:
collect dev-resources in a separate directory out of assets (in my case lib/devdata/)
create a Builder implementation and a build.yaml file
in build.yaml create separate dev_properties that allow the builder to behave according to the build mode, i.e. either copy the files to assets/devdata/ or delete them in assets/devdata/ and this directory to .gitignore
add assets/devdata/ to assets in pubspec.yaml
run build_runner either in dev or in prod mode to copy or delete the files
consume the files in the app using rootBundle if they are present / catch the resulting exception if they are absent
this command invokes the build_runner in dev / release mode respectively:
$ flutter pub run build_runner build
$ flutter pub run build_runner build --release
the builder looks roughly as follows (saved in lib/devdata/devdata.dart):
import 'dart:async';
import 'dart:io';
import 'package:build/build.dart';
Builder devData(BuilderOptions options) => DevDataBuilder(options);
class DevDataBuilder implements Builder {
final BuilderOptions options;
DevDataBuilder(this.options);
#override
FutureOr<void> build(BuildStep buildStep) async {
var mode = options.config['mode'];
var inputId = buildStep.inputId;
var sourcePath = inputId.path;
var targetPath = sourcePath.replaceFirst('lib/devdata/', 'assets/devdata/');
final outputId = AssetId(
inputId.package,
targetPath,
);
if (mode == 'dev') {
log.info('copying $sourcePath to $targetPath');
var contents = await buildStep.readAsString(inputId);
await buildStep.writeAsString(outputId, contents);
} else {
var file = File(targetPath);
if (await file.exists()) {
log.info('deleting $targetPath');
file.delete();
}
}
}
#override
Map<String, List<String>> get buildExtensions {
return {
'lib/devdata/{{file}}.json': const ['assets/devdata/{{file}}.json'],
};
}
}
the corresponding build.yaml is here:
builders:
test_data:
import: 'package:my_app_package/builder/devdata.dart'
builder_factories: ['devData']
build_extensions: {"lib/devdata/{{file}}.json": ["assets/testdata/{{file}}.json"]}
build_to: source
auto_apply: root_package
defaults:
generate_for:
include:
- lib/devdata/**
global_options:
my_app_package:test_data:
options:
mode: prod
dev_options:
mode: dev
here are some additional resources that led to this approach:
https://pub.dev/packages/build
https://pub.dev/packages/build_config
https://pub.dev/packages/build_runner
https://github.com/dart-lang/build/tree/master/example
https://github.com/dart-lang/build/blob/master/docs/build_yaml_format.md
https://pedromarquez.dev/blog/2022/8/flutter-code-gen-1
https://pedromarquez.dev/blog/2022/9/flutter-code-gen-2
https://github.com/flutter/flutter/issues/5813
https://github.com/flutter/flutter/pull/25487
an alternative approach without a builder can be found here (using the pr #25487 mentioned above):
https://github.com/sestegra/flutter_assets_flavors

How to fix Flutter stream exiting whenever i try to listen to it

In a flutter app, I'm trying to read a large csv file one line at a time by opening a stream on it. The issue is that when i try to listen to the stream the execution just skips over that code block and the program ends.
The file I'm opening is located in my assets folder and I've confirmed programmatically that it does exist before opening the stream. Changing the file the stream is opened on doesn't help, the same problem persists. I've also tried to change the way i listen to the stream, following different methods provided by Darts official documentation (that code is commented out) but the outcome is again the same. The assets have been declared in the pubspec.yaml. When i change the code to read the file as a String the program works perfectly but I want to use a stream because the file is so massive that creating a String object for it would take a large amount of time and memory.
void trainDigitsStream() async{
List<List<List>> filters = createRandomFilter(4, 4, 1, -1, 1);
List flattened= new List<double>();
File file = new File("assets/digit_train_data.csv");
if(file.existsSync())print("EXISTS!");
Stream<List<int>> stream = file.openRead();
Stream lines = utf8.decoder.bind(stream).transform(LineSplitter());
/*
try{
await for (var line in lines){
print(line);
}
print("file ended");
}catch(e){
print(e);
}
*/
lines.listen((data){//code exits here, execution never reaches next line
String line = data.toString();
List<List> instance = new List<List<int>>();
List x = new List<int>();
int i = 0;
line.split(',').forEach((d){
x.add(int.parse(d));
i++;
if(i == 28){
instance.add(x);
x = new List<int>();
i = 0;
}
});
List<List<List>> kernels = new List<List<List<double>>>();
List<List> pools = new List<List>();
filters.forEach((f){kernels.add(convo.applyFilter(instance, f, 0));});
kernels.forEach((k){pools.add(pool.maxPool(k, 2));});
pools.forEach((p){flattened.addAll(p);});
});
}
It's hard without further information, It would be better if you can post more information.
So I guess the problem should be , please check the following two steps.
1. Register the assets folder in pubspec.yaml
flutter:
assets:
- assets/digit_train_data.csv
2. You need to use rootBundle to access this csv file, reference document https://flutter.dev/docs/development/ui/assets-and-images
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/digit_train_data.csv');
}
similar question here Flutter - Read text file from assets