API Androida niestety nie dostarcza nam w standardzie żadnego mechanizmu umożliwiającego wybór pliku z systemu plików. W takim przypadku nie pozostaje nam nic innego jak zaimplementować to samemu lub skorzystać z gotowej biblioteki.
Postanowiłem bazować na file chooser’ze zaimplementowanym przez Rogera Keaysa. Jest on dostępny pod poniższym adresem: https://rogerkeays.com/simple-android-file-chooser.
Moja implementacja wygląda w następujący sposób:
class FileChooser(val activity: Activity, val fileListener: FileSelectedListener, val maxFileSize: Double) {
private lazy val messageMaker = wire(classOf[MessageMaker])
private val parentDir = ".."
private val mb = 1024.0 * 1024.0
private val dialog = new Dialog(activity)
private val list = new ListView(activity)
private var currentPath: File = _
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
override def onItemClick(parent: AdapterView[_], view: View, position: Int, id: Long): Unit = {
val fileChosen: String = list.getItemAtPosition(position).asInstanceOf[String]
val chosenFile: File = getChosenFile(fileChosen)
if (chosenFile.isDirectory) {
refresh(chosenFile)
}
else {
val sizeInMB: Double = chosenFile.length / mb
if (sizeInMB > maxFileSize) {
messageMaker.info("Selected file is too large")
}
else {
if (fileListener != null) {
fileListener.fileSelected(chosenFile)
}
dialog.dismiss()
}
}
}
})
dialog.setContentView(list)
dialog.getWindow.setLayout(MATCH_PARENT, MATCH_PARENT)
refresh(Environment.getExternalStorageDirectory)
def showDialog() {
dialog.show()
}
/**
* Sort, filter and display the files for the given path.
*/
private def refresh(path: File) {
this.currentPath = path
if (path.exists) {
val dirs: Array[File] = path.listFiles(new FileFilter() {
def accept(file: File): Boolean = {
file.isDirectory && file.canRead
}
})
val files: Array[File] = path.listFiles(new FileFilter() {
def accept(file: File): Boolean = {
!file.isDirectory && file.canRead
}
})
dirs.sortWith(_.getName > _.getName)
files.sortWith(_.getName > _.getName)
// convert to an array
val i: Int = 0
var fileList = ArrayBuffer[String]()
if (path.getParentFile != null) {
fileList += parentDir
}
dirs.foreach(d => fileList += d.getName)
files.foreach(f => fileList += f.getName)
// refresh the user interface
dialog.setTitle(currentPath.getPath)
list.setAdapter(new ArrayAdapter(activity, android.R.layout.simple_list_item_1, fileList.toArray) {
override def getView(pos: Int, view: View, parent: ViewGroup): View = {
val superView = super.getView(pos, view, parent)
superView.asInstanceOf[TextView].setSingleLine(true)
superView
}
})
}
}
private def getChosenFile(fileChosen: String): File = {
if (fileChosen == parentDir) {
currentPath.getParentFile
}
else {
new File(currentPath, fileChosen)
}
}
}
trait FileSelectedListener {
def fileSelected(file: File)
}
Główną zmianą (oczywiście poza napisaniem tego w języku Scala) jest dodanie ograniczenia na maksymalną wielkość pliku. Po wyborze pliku, jeżeli jego rozmiar przekracza ustawiony maksymalny rozmiar to zostaje wyświetlony komunkat z informacją, a plik nie zostaje dodany.


Dodaj komentarz