To be able to use assets in the Flutter Plugin, firstly, we need to add the resources inside the plugins's folder, in this example, I am placing the clap.wav
file in the folder [your_plugin_project_name]/ios/Assets/
.
After adding the file inside the plugin's folder, we need to specify in the plugin's PodSpec where the assets are located.
# File [your_plugin_project_name]/my_flutter_plugin.podspec
Pod::Spec.new do |s|
# [...] supressed content above
s.source_files = 'Classes/**/*'
s.resources = ['Assets/**.*']
# [...] supressed content below
end
The important part in the snippet above is the line s.resources = ['Assets/**.*']
, where Assets/**/*
specify that all the plugin's resources are inside the folder Assets
. The Assets/**/*
is a wildcard used to tell that every file (the *
string part) in every folder/subfolder (the **
part) within the folder Assets
must be included as resources of the plugin's bundle. You can learn more about this kind of string searching about regular expression
.
Every time you change the plugin's configuration, you'll need to inform the Flutter's project using the plugin that there are new changes. In a regular project, you would need to bump the plugin's version and release a new version of it in the Pub, but as we are just changing this locally (without releasing it to the world), we need only to inform Flutter that the plugin's files are outdated. The easiest way to do that is to run flutter clean
inside the project that is using the plugin.
After that, you will be able to access the clap.wav
file in the plugins's swift files using the code:
guard let url = Bundle(for: type(of: self)).url(forResource: "clap", withExtension: "wav") else {
return print("File not found")
}
Notice that you must use Bundle(for: type(of: self))
instead of Bundle.main
(the Bundle.main
points to the Runner's bundle instead of your plugin's bundle).
I the example below, I show how you could play the clap.wav
using swift code:
import Flutter
import UIKit
import AVFoundation
public class SwiftMyFlutterPlugin: NSObject, FlutterPlugin {
private var player: AVAudioPlayer?
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "my_flutter_plugin", binaryMessenger: registrar.messenger())
let instance = SwiftMyFlutterPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
return result("iOS " + UIDevice.current.systemVersion)
case "playSound":
return playSound(result: result)
default:
return result(FlutterMethodNotImplemented)
}
}
private func playSound(result: @escaping FlutterResult) {
if player?.isPlaying == true { return }
let filename = "clap"
let fileExtension = "wav"
guard let url = Bundle(for: type(of: self)).url(forResource: filename, withExtension: fileExtension) else {
let flutterError = FlutterError(
code: "fileNotFound",
message: "File not found: \(filename).\(fileExtension).",
details: nil
)
return result(flutterError)
}
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
let flutterError = FlutterError(
code: "audioSessionSetupError",
message: "Error on AVAudionSession setup.",
details: error.localizedDescription
)
return result(flutterError)
}
do {
player = try AVAudioPlayer(contentsOf: url)
player?.play()
} catch {
let flutterError = FlutterError(
code: "audioPlayerSetupError",
message: "Error on AVAudioPlayer setup.",
details: error.localizedDescription
)
return result(flutterError)
}
}
}
The example above is a simple example of how you could play the clap.wav
file, but you could do in different other ways. As this is not related with the question, I think that the example above is enough to answer your question.
To facilitate your understanding and easily demonstrate that the code above works, I created a simple project in the GitHub that you can execute to see that this works as expected, see it here.
Notice that you must run the code inside the folder example
.