Android – Trình duyệt File

Rate this post

Trong phần này chúng ta sẽ xây dựng một ứng dụng file explorer (duyệt file) đơn giản.

Chúng ta tạo project với tên FileExplorer, file ActivityMainActivity.java, file layout cho Activity này là main.xml.

Main Layout

Trong file main.xml chúng ta thiết kế như sau:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    androd:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <TextView 
        android:id="@+id/txtPath" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="Path:" />
    <Button 
        android:id="@+id/btnBrowse" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
         android:text="Browse" android:onClick="onClicked"/>
</LinearLayout>

Chúng ta thiết kế một TextView và một Button, TextView sẽ hiển thị đường dẫn tuyệt đối đến file mà người dùng chọn, Button được dùng để mở một Activity khác để duyệt file, phương thức xử lý sự kiện của ButtononClicked().

MainActivity

Tiếp theo là file MainActivity.java:

package com.phocode;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.content.Intent;
import android.widget.TextView;

public class MainActivity extends Activity
{
    private static final int FILE_CHOOSER_CODE = 1;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
 
    public void onClicked(View view)
    {
        Intent fileChooserIntent = new Intent(this, FileChooserActivity.class);
        startActivityForResult(fileChooserIntent, FILE_CHOOSER_CODE);
    }
 
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        if(requestCode == FILE_CHOOSER_CODE)
            if(resultCode == RESULT_OK)
            {
                String fullPath = data.getStringExtra("FullPath");
                TextView path = (TextView) findViewById(R.id.txtPath);
                path.setText(fullPath);
            }
    }
}

Lớp MainActivity sẽ hiển thị màn hình của file layout main.xml và chịu trách nhiệm mở lớp FileChooserActivity để duyệt file.

private static final int FILE_CHOOSER_CODE = 1;

Chúng ta định nghĩa code để mở Activity mới.

public void onClicked(View view)
{
    Intent fileChooserIntent = new Intent(this, FileChooserActivity.class); 
    startActivityForResult(fileChooserIntent, FILE_CHOOSER_CODE);
}

Trong phương thức onClicked(), chúng ta tạo một đối tượng Intent mới và gọi phương thức startActivityForResult() để mở lớp FileChooserActivity mà chúng ta sẽ viết ở dưới.

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if(requestCode == FILE_CHOOSER_CODE)
        if(resultCode == RESULT_OK)
        {
            String fullPath = data.getStringExtra("FullPath");
            TextView path = (TextView) findViewById(R.id.txtPath);
            path.setText(fullPath);
        }
}

Phương thức onActivityResult() sẽ nhận kết quả trả về của lớp FileChooserActivity là đường dẫn tuyệt đối của file mà người dùng chọn khi duyệt file, chúng ta lấy đường dẫn đó gán vào TextView.

ListView Layout

Không giống như các bài trước, chúng ta sử dụng ListView chỉ để hiển thị những chuỗi string đơn lẻ, ở đây mỗi item của ListView sẽ hiển thị tên file hoặc tên thư mục đi kèm với kích thước file nếu có. Nên chúng chúng ta thiết kế các item này giống như thiết kế một giao diện cho Activity vậy.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" 
    android:padding="5dp">
    <TextView 
        android:id="@+id/name" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:textSize="20sp" 
        android:padding="10dp"/>
    <TextView 
        android:id="@+id/size" 
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:textSize="10sp"/>
</LinearLayout>

Chúng ta sẽ dùng 2 TextView, một dùng để hiển thị tên file hoặc thư mục, một dùng để hiển thị kích thước file nếu có.

FileChooserActivity

Tiếp theo là lớp FileChooserActivity.

package com.phocode;

import android.app.ListActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;

public class FileChooserActivity extends ListActivity 
{
    private ItemArrayAdapter la;
    private List<Item> itemArr;
    private String currentDirectory; 

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
 
        currentDirectory = "/";
        generateContent(currentDirectory);
    }
 
    @Override
    public void onListItemClick(ListView listView, View view, int position, long id)
    { 
        Item selectedItem = (Item)getListAdapter().getItem(position);
        String newPath = ""; 
        if(selectedItem.getName().equals("..")) 
            newPath = new File(currentDirectory).getParent(); 
        else
        {
            newPath = currentDirectory;
            if(currentDirectory.equals("/") == false) 
            newPath += "/";
            newPath += selectedItem.getName(); 
        }
        File newFile = new File(newPath); 
        if(newFile.isDirectory())
        { 
            currentDirectory = newPath;
            generateContent(currentDirectory); 
        } 
        else
        {
            Intent intent = new Intent();
            intent.putExtra("FullPath", newPath);
            setResult(RESULT_OK, intent);
            finish();
        }
    }
 
    private void generateContent(String path)
    {
        File f = new File(path);
        ArrayList<File> files = new ArrayList<File>(Arrays.asList(f.listFiles()));
 
        int fileSize = files.size(); 
        itemArr = new ArrayList();
        if(path.equals("/") == false) itemArr.add(new Item("..", 0));
 
        for(int i = 0 ; i < fileSize ; i++)
        {
            String name = files.get(i).getName();
            int size;
            if(files.get(i).isDirectory())
                size = 0;
            else
                size = (int)files.get(i).length(); 
            itemArr.add(new Item(name, size)); 
        } 
        la = new ItemArrayAdapter(this, itemArr);
 
        setListAdapter(la);
    }
}

Lớp FileChooserActivity sẽ có giao diện để người dùng chọn file hoặc thư mục.

currentDirectory = "/";

Chúng ta định nghĩa biến currentDirectory dùng để lưu đường dẫn đến file hoặc thư mục được chọn. Mặc định khi chạy ứng dụng thì thư đây là đường dẫn đến thư mục gốc, thư mục gốc trong các hệ điều hành linux và Android là dấu "/".

private void generateContent(String path)
{
...
}

Khi Activity này được khởi động, phương thức generateContent() sẽ tìm danh sách các thư mục và file trong tham số path và đưa chúng lên màn hình.

File f = new File(path);
ArrayList<File> files = new ArrayList<File>(Arrays.asList(f.listFiles()));

Đầu tiên chúng ta lấy danh sách các thư mục và file và lưu trong một đối tượng ArrayList<File>. Phương thức File.listFiles() sẽ trả về danh sách các thư mục và file hiện có dưới dạng mảng, phương thức Arrays.asList() sẽ chuyển mảng thành kiểu List.

itemArr = new ArrayList();
if(path.equals("/") == false) itemArr.add(new Item("..", 0));

Chúng ta sẽ thực hiện lưu các đối tượng file/thư mục trong danh sách itemArr, đây là một đối tượng List<Item>, chúng ta sẽ viết lớp Item ở dưới. Ngoài ra ở đây chúng ta còn kiểm tra xem thư mục hiện tại mà người dùng đang duyệt có phải là thư mục gốc hay không, nếu không thì chúng ta chèn thêm một đối tượng ".." nữa, dấu ".." nghĩa là lùi thư mục hiện tại về một cấp, chẳng hạn như chúng ta đang ở /sdcard/musics thì lùi một cấp sẽ thành /sdcard.

for(int i = 0 ; i < fileSize ; i++)
{
...
} 

Trong vòng lặp for chúng ta tiến hành kiểm tra xem các đối tượng File là thư mục hay là file để tạo đối tượng Item tương ứng. Phương thức length() sẽ trả về kích thước của file, nếu đối tượng hiện tại là thư mục thì chúng ta gán kích thước là 0.

la = new ItemArrayAdapter(this, itemArr);
 
setListAdapter(la);

Cuối cùng chúng ta thiết lập ArrayAdapter để ListView có thể nhận dữ liệu. Ở đây vì ListView của chúng ta không chỉ hiển thị một phần tử đơn lẻ mà hiển thị nhiều phần tử cùng một lúc nên chúng ta phải tùy chỉnh lại lớp ArrayAdapter.

@Override
public void onListItemClick(ListView listView, View view, int position, long id)
{
... 
}

Phương thức onListItemClick() sẽ tự động được gọi mỗi khi chúng ta click vào một item nào đó trên ListView. Trong phương thức này chúng ta kiểm tra xem nếu người dùng click vào một thư mục thì chúng ta khởi tạo lại một đối tượng ArrayAdapter mới, nếu người dùng click vào một file thì chúng ta tắt Activity tại đây và gửi trả về đường dẫn đến file mà đó, nếu người dùng click vào nút ".." thì chúng ta cho lùi thư mục về một cấp.

ItemArrayAdapter

package com.phocode;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

public class ItemArrayAdapter extends ArrayAdapter<Item>
{
    private Context context;
    private List<Item> values;
 
    public ItemArrayAdapter(Context context, List<Item> values)
    {
        super(context, R.layout.row, values);
        this.context = context;
        this.values = values;
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
        View row = inflater.inflate(R.layout.row, parent, false);
        TextView name = (TextView) row.findViewById(R.id.name);
        TextView size = (TextView) row.findViewById(R.id.size);
 
        Item currentItem = values.get(position);
 
        name.setText(currentItem.getName());
        if(currentItem.getSize() > 0)
            size.setText(String.valueOf(currentItem.getSize()) + " bytes");
        else
            size.setText("");
        return row;
    }
}

Lớp ItemArrayAdapter sẽ kế thừa từ lớp ArrayAdapter.

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
...
}

Chúng ta tùy chỉnh cách mà các item sẽ được hiển thị trong phương thức getView().

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
View row = inflater.inflate(R.layout.row, parent, false);
TextView name = (TextView) row.findViewById(R.id.name);
TextView size = (TextView) row.findViewById(R.id.size);

Chúng ta lấy 2 phần tử TextView trong file layout.

name.setText(currentItem.getName());
if(currentItem.getSize() > 0)
    size.setText(String.valueOf(currentItem.getSize()) + " bytes");
else
    size.setText("");

Với mỗi item trên ListView, nếu item đó là file thì chúng ta hiển thị tên file và kích thước file, còn nếu là thư mục thì chúng ta không cho hiển thị kích thước.

Item

Cuối cùng là lớp Item.

package com.phocode;

public class Item
{
    private String name;
    private int size;
 
    public Item()
    {
        this.name = "";
        this.size = 0;
    }
 
    public Item(String name, int size)
    {
        this.name = name;
        this.size = size;
    }
 
    public String getName() { return this.name; }
    public int getSize() { return this.size; }
 
    public void setName(String name) { this.name = name; }
    public void setSize(int size) { this.size = size; }
}

Lớp Item là lớp dùng để lưu thông tin về từng Item trên ListView, bao gồm tên file/thư mục và kích thước file đó.

Screenshot_2016-05-28-17-51-26 Screenshot_2016-05-28-17-51-35

 

0 0 votes
Article Rating
Subscribe
Thông báo cho tôi qua email khi
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments