How to access assets in package - flutter

The original question comes from flutter issue 32799
I develop a dart package, i need load some json file in runtime, but when I do this occur an error. load image is no problem ,the code:
void main() {
Future<void> loadAsset() async {
String value = await rootBundle
.loadString('lib/src/assets/JsonConfig/test.json');
//Image img = Image.asset('lib/src/assets/default-logo.png');
}
test('adds one to input values', () async {
await loadAsset();
});
}
my pubspec.yaml file like this:
flutter:
# To add assets to your package, add an assets section, like this:
assets:
- lib/src/assets/default-logo.png
- lib/src/assets/JsonConfig/test.json
- lib/src/assets/

To load assets from packages, you should add the prefix 'packages/<package_name>/' for the key to making it works.
Such as how AssetImage do
/// The name used to generate the key to obtain the asset. For local assets
/// this is [assetName], and for assets from packages the [assetName] is
/// prefixed 'packages/<package_name>/'.
String get keyName => package == null ? assetName : 'packages/$package/$assetName';
https://github.com/flutter/flutter/blob/fba99f6cf9a14512e461e3122c8ddfaa25394e89/packages/flutter/lib/src/painting/image_resolution.dart#L146
So add the prefix 'packages/<package_name>/' for the key will work on the demo above:
String value = await rootBundle
.loadString('packages/<package_name>/lib/src/assets/JsonConfig/test.json');

Related

Assets is being loaded in cache but not found for AudioPlayer

I'm using the package: audioplayers: ^1.0.1
I'm trying to follow the migration guide of audioplayers found in this link: https://github.com/bluefireteam/audioplayers/blob/main/migration_guide.md
But I can't make it to work.
Here's my pubspec
flutter:
assets:
- assets/sounds/
If I do it like this, it can't load the assets.
final playerSound = AudioPlayer();
await playerSound.setSource(AssetSource('assets/sounds/Pop (1).wav'));
Unhandled Exception: Unable to load asset: assets/assets/sounds/Pop (1).wav
But if I remove the assets, it is trying to find in the cache. I don't get why it is working. Please help to clarify. Thanks!
final playerSound = AudioPlayer();
await playerSound.setSource(AssetSource('sounds/Pop (1).wav'));
java.io.FileNotFoundException: /data/user/0/com.MyName.MyApp/cache/sounds/Pop%20(1).wav: open failed: ENOENT (No such file or directory)
Ok so what i see from the package structure.
If you Go into the AssetSource class which looks as follows :
source.dart file
/// Source representing the path of an application asset in your Flutter
/// "assets" folder.
/// Note that a prefix might be applied by your [AudioPlayer]'s audio cache
/// instance.
class AssetSource extends Source {
final String path;
AssetSource(this.path);
#override
Future<void> setOnPlayer(AudioPlayer player) {
return player.setSourceAsset(path);
}
}
Here if you go inside the setSourceAsset method :
/// Sets the URL to an asset in your Flutter application.
/// The global instance of AudioCache will be used by default.
///
/// The resources will start being fetched or buffered as soon as you call
/// this method.
Future<void> setSourceAsset(String path) async {
final url = await audioCache.load(path);
return _platform.setSourceUrl(playerId, url.path, isLocal: true);
}
if you see the line
final url = await audioCache.load(path);
so this in this AudioCache class if you see the constructor :
/// This is the path inside your assets folder where your files lie.
///
/// For example, Flame uses the prefix 'assets/audio/'
/// (you must include the final slash!).
/// The default prefix (if not provided) is 'assets/'
/// Your files will be found at <prefix><fileName> (so the trailing slash is
/// crucial).
String prefix;
AudioCache({this.prefix = 'assets/'});
So the prefix is assets added as a default in the constructor. So you don't have to call it every time only the file name followed by the folder if you are adding in any case.
After removing the spaces in the name. It is now working. Thanks to #Olek L. and #farouk osama

Is there any option to hide/ remove .hive files?

When I used hive as local db in flutter, .hive files are generated in user's app-directory. Is there any way to hide or remove these files from the app-directory?
You can remove file which contains the box and closes the box by using this method.
deleteFromDisk
Use path_provider to store hive file in getApplicationSupportDirectory
Future<void> init() async {
final path = await getApplicationSupportDirectory();
await Hive.initFlutter();
Hive.registerAdapter(UserAdapter());
await Hive.openBox<User>(HiveConst.userDataBox, path: path.path);
}

How to get property AssetName from Image.asset in Flutter?

From an AssetImage object i'm trying to get the file name in Flutter.
Image photo = Image.asset('assets/images/image-not-found.jpg');
print(photo.image); // AssetImage(bundle: null, name: "assets/images/image-not-found.jpg")
print(photo.image.assetName); // assetName not defined
print(photo.image.name); // name not defined
How to get this assetName property?
Something nicer without doing some regex on photo.image.toString();
EDIT:
the purpose here was to retrieve the image name in order to compare it.
So i just go for direct comparaison.
if(photo.image == AssetImage('assets/images/image-not-found.jpg')){
print("image was not found");
}
Try AssetImage for this.
var photo = AssetImage('assets/images/image-not-found.jpg');
print(photo.assetName);
//You can use split method like
`String toSplit = 'assets/images/image-not-found.jpg';
var imageName = toSplit.split("/");
print(var[2]);`
//You can get your image name stored in var[2].
First, add an asset folder in pubspec file like:
assets:
- specify a folder where is your assets are stored.
and use like this
Image.asset(
'assets/images/profile.png',
fit: BoxFit.fill,
),

How can I display Asset Images on Flutter web?

When I try to display an asset in Flutter Web using the following syntax, no image is shown:
Image.asset(
'assets/image.png',
)
On mobile, the same code will show an image.
The structure is as follows:
assets
image.png
lib
...
pubspec.yaml
In the Pubspec, I declare the asset like this:
flutter:
assets:
- assets/image.png
All assets are stored in an assets directory in Flutter Web, which means that the image asset will be stored like this on web:
assets
assets
image.png
index.html
...
With this knowledge, we can create a widget that handles the behavior for both mobile and web.
Note that we can use Image.network on web because the images are accessed through the network on web by default (that is how web works in general). The path would be yourdomain.com/assets/assets/image.png.
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
class PlatformAwareAssetImage extends StatelessWidget {
const PlatformAwareAssetImage({
Key key,
this.asset,
this.package,
}) : super(key: key);
final String asset;
final String package;
#override
Widget build(BuildContext context) {
if (kIsWeb) {
return Image.network(
'assets/${package == null ? '' : 'packages/$package/'}$asset',
);
}
return Image.asset(
asset,
package: package,
);
}
}
Potentially, this will be changed in future Flutter versions - this is the state of things as of v1.18.0-6.0.pre.82.
For some reason, assets in the web builds are currently placed under another assets/ directory, which results in the path being assets/assets/....
Create a simple function e.g. in lib/utils.dart:
import 'package:flutter/foundation.dart';
String path(str) {
return (kIsWeb) ? 'assets/$str' : str;
}
Wrap any path strings with this function, for example AssetImage(path('images/bg.jpg')).
I find this simpler:
Image.asset("${(kDebugMode && kIsWeb)?"":"assets/"}images/mds_square.png"),
I always need the "assets/" prefix since my "images" folder are in "assets" folder; however, in web debug I need to emit the "assets/" prefix.

Flutter check if Asset image exists

Is it possible to conditionally load an asset image, only if it exists? Therefore you could load a default image if it does not exist in the Assets bundle.
One way you can check if the asset image exists is by trying to display it. If it throws an Exception, display a different widget instead.
Future<Widget> getAssetImage(String path) async {
try {
await rootBundle.load(path);
return Image.asset(path);
} catch (_) {
return SizedBox(); // Return this widget
}
}
Otherwise, you can check the AssetManifest.json and cross-check the asset to be used with the list before trying to access it.