第一次寫(xiě)文章够委,作為自己學(xué)習(xí)flutter過(guò)程中做一些記錄吧
最近在項(xiàng)目的過(guò)程中涉及到要訪問(wèn)內(nèi)存卡荐类,并且打開(kāi)文件的情況。調(diào)用原生的文件管理器效果不太理想茁帽,所以想著用flutter自定義一個(gè)玉罐。好了,開(kāi)始吧潘拨!
創(chuàng)建一個(gè)flutter項(xiàng)目開(kāi)始寫(xiě)代碼吊输。
要訪問(wèn)SD卡,首先讀取權(quán)限肯定是要有的铁追,不然寫(xiě)再多代碼都是無(wú)用功季蚂。
在AndroidManifest.xml文件中添加
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
新建一個(gè)dart文件file_manager.dart
這里需要使用到一個(gè)插件path_provider
用來(lái)獲取SD卡根路徑(不嫌麻煩自己寫(xiě)原生也可以),在pubspec.yaml
文件里添加相關(guān)依賴(lài)即可path_provider: ^0.4.1
琅束。
然后在初始化函數(shù)使用String sDCardDir = (await getExternalStorageDirectory()).path;
獲得SD卡的根路徑(一定要在初始化函數(shù)中就調(diào)用扭屁,不然運(yùn)行之后連個(gè)路徑都沒(méi)),從這個(gè)路徑就可以找出SD卡的所有文件和文件夾涩禀。
拿到這個(gè)路徑后使用directory.listSync()
會(huì)自動(dòng)找出當(dāng)前目錄下所有文件和文件夾
List<FileSystemEntity> files = [];
var directory = Directory(sDCardDir);
files = directory.listSync();
把SD卡根目錄下的所有文件疯搅、文件夾都存放到files
中,這也是這個(gè)文件管理器最核心的方法埋泵,傳入根目錄路徑就能找出根路徑下的所有文件和文件夾,那把其中一個(gè)文件夾的路徑再傳進(jìn)去(點(diǎn)擊一個(gè)文件夾的時(shí)候罪治,傳遞該文件夾路徑)丽声,就能找出這個(gè)文件夾里的所有文件和文件夾啦~
頁(yè)面顯示的時(shí)候使用了ListView
布局,因?yàn)槲募?shù)量不確定觉义,也可能會(huì)很大雁社,所以使用了ListView.builder
進(jìn)行構(gòu)建。具體代碼如下:
ListView.builder(
controller: controller,
itemCount: files.length,
itemBuilder: (BuildContext context, int index) {
return buildListViewItem(files[index]);
},
),
返回的buildListViewItem
就是具體的布局晒骇,簡(jiǎn)單使用ListTile
就可以完成比較好看的顯示效果了霉撵。代碼還是貼上來(lái):
Column(
children: <Widget>[
ListTile(
leading: Image.asset(selectIcon(isFile, file)),
title: Row(
children: <Widget>[
Expanded(child: Text(file.path.substring(file.parent.path.length + 1))),
isFile
? Container()
: Text(
'$length項(xiàng)',
style: TextStyle(color: Colors.grey),
)
],
),
subtitle: isFile
? Text(
'${getFileLastModifiedTime(file)} ${getFileSize(file)}',
style: TextStyle(fontSize: 12.0),
)
: null,
trailing: isFile ? null : Icon(Icons.chevron_right),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 14.0),
child: Divider(
height: 1.0,
),
)
],
),
那如何判斷這是一個(gè)文件還是文件夾呢磺浙?這里有一個(gè)方法
var isFile = FileSystemEntity.isFileSync(file.path);
這是一個(gè)bool類(lèi)型的值,true表示是文件徒坡,false就是文件夾啦撕氧。
在后面的顯示上就可以通過(guò)這個(gè)來(lái)區(qū)分了。
還有一些頁(yè)面顯示美化的代碼就不貼了喇完,后面有項(xiàng)目地址可以自己下載下來(lái)看看伦泥。
打開(kāi)文件
文件管理器,看到的文件應(yīng)該要能打開(kāi)吧锦溪。下面就是判斷點(diǎn)擊的是文件時(shí)不脯,要彈出提示用什么應(yīng)用去打開(kāi),要寫(xiě)一點(diǎn)原生刻诊,不過(guò)也不難防楷。
自己寫(xiě)一個(gè)通道的方法,去調(diào)用
file_manager.dart
MethodChannel _channel = MethodChannel('openFileChannel');
openFile(String path) {
final Map<String, dynamic> args = <String, dynamic>{'path': path};
_channel.invokeMethod('openFile', args);
}
然后在MainActivity.java
文件中定義
private static Context mContext = null;
private static final String METHOD_CHANNEL = "openFileChannel";
"openFileChannel"
名字要對(duì)應(yīng)一致
然后在onCreate方法中增加以下代碼
new MethodChannel(getFlutterView(), METHOD_CHANNEL).setMethodCallHandler(
new MethodCallHandler() {
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
if (methodCall.method.equals("openFile")) {
String path = methodCall.argument("path");
openFile(mContext, path);
result.success("");
} else {
result.notImplemented();
}
}
}
);
方法名為openFile
则涯,其實(shí)只有一個(gè)方法好像不用指定也是可以的复局,不過(guò)為了規(guī)范一點(diǎn),還是寫(xiě)上比較好是整。
dart那邊傳給Java層的是一個(gè)文件的路徑肖揣,然后調(diào)用openFile()方法,方法實(shí)現(xiàn)如下
private void openFile(Context context, String path) {
try {
if (!path.contains("file://")) {
path = "file://" + path;
}
//獲取文件類(lèi)型
String[] nameType = path.split("\\.");
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(nameType[1]);
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_VIEW);
//設(shè)置文件的路徑和文件類(lèi)型
intent.setDataAndType(Uri.parse(path), mimeType);
//跳轉(zhuǎn)
context.startActivity(intent);
} catch (Exception e) {
System.out.println(e);
}
}
使用Intent的方式去打開(kāi)浮入,這里還是加上try...catch...吧龙优,因?yàn)橛行┪募?lèi)型好像會(huì)報(bào)錯(cuò),具體原因還沒(méi)去深究事秀,應(yīng)該是一些系統(tǒng)文件(有些連文件后綴都沒(méi)...)
整個(gè)文件管理器的實(shí)現(xiàn)主要方法就到這里了
實(shí)現(xiàn)的界面如下
項(xiàng)目的代碼已經(jīng)上傳到我的GitHub彤断,如果覺(jué)得對(duì)你有幫助歡迎star,同時(shí)也會(huì)繼續(xù)更新完善