java - 如何使用文件观察器?

标签 java android

网上有一个非常流行的类,RecursiveFileObserver,它可以用来递归地检测对文件系统所做的任何读/写更改,这个类可以在 here 找到。 , here ,还有here 。但问题是我该如何使用这个类?我把它复制到我的项目中,但它没有做任何事情。我该如何开始呢? 我是初学者。

package com.toraleap.collimator.util;
//from   w  w w .j  a  v  a  2s.c  o  m
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import android.os.FileObserver;
import android.util.Log;

/**
 * Enhanced FileObserver to support recursive directory monitoring basically.
 * @author    uestc.Mobius <mobius@toraleap.com>
 * @version  2011.0121
 */
public class RecursiveFileObserver extends FileObserver {
    /** Only modification events */
    public static int CHANGES_ONLY = CREATE | DELETE | CLOSE_WRITE | MOVE_SELF | MOVED_FROM | MOVED_TO;

    List<SingleFileObserver> mObservers;
    String mPath;
    int mMask;

    public RecursiveFileObserver(String path) {
        this(path, ALL_EVENTS);
    }

    public RecursiveFileObserver(String path, int mask) {
        super(path, mask);
        mPath = path;
        mMask = mask;
    }

    @Override
    public void startWatching() {
        if (mObservers != null) return;

        mObservers = new ArrayList<SingleFileObserver>();
        Stack<String> stack = new Stack<String>();
        stack.push(mPath);

        while (!stack.isEmpty()) {
            String parent = stack.pop();
            mObservers.add(new SingleFileObserver(parent, mMask));
            File path = new File(parent);
            File[] files = path.listFiles();
            if (null == files) continue;
            for (File f : files)
            {
                if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) {
                    stack.push(f.getPath());
                }
            }
        }

        for (SingleFileObserver sfo : mObservers) {
            sfo.startWatching();
        }
    }

    @Override
    public void stopWatching() {
        if (mObservers == null) return;

        for (SingleFileObserver sfo : mObservers) {
            sfo.stopWatching();
        }
        mObservers.clear();
        mObservers = null;
    }

    @Override
    public void onEvent(int event, String path) {
        switch (event)
        {
            case FileObserver.ACCESS:
                Log.i("RecursiveFileObserver", "ACCESS: " + path);
                break;
            case FileObserver.ATTRIB:
                Log.i("RecursiveFileObserver", "ATTRIB: " + path);
                break;
            case FileObserver.CLOSE_NOWRITE:
                Log.i("RecursiveFileObserver", "CLOSE_NOWRITE: " + path);
                break;
            case FileObserver.CLOSE_WRITE:
                Log.i("RecursiveFileObserver", "CLOSE_WRITE: " + path);
                break;
            case FileObserver.CREATE:
                Log.i("RecursiveFileObserver", "CREATE: " + path);
                break;
            case FileObserver.DELETE:
                Log.i("RecursiveFileObserver", "DELETE: " + path);
                break;
            case FileObserver.DELETE_SELF:
                Log.i("RecursiveFileObserver", "DELETE_SELF: " + path);
                break;
            case FileObserver.MODIFY:
                Log.i("RecursiveFileObserver", "MODIFY: " + path);
                break;
            case FileObserver.MOVE_SELF:
                Log.i("RecursiveFileObserver", "MOVE_SELF: " + path);
                break;
            case FileObserver.MOVED_FROM:
                Log.i("RecursiveFileObserver", "MOVED_FROM: " + path);
                break;
            case FileObserver.MOVED_TO:
                Log.i("RecursiveFileObserver", "MOVED_TO: " + path);
                break;
            case FileObserver.OPEN:
                Log.i("RecursiveFileObserver", "OPEN: " + path);
                break;
            default:
                Log.i("RecursiveFileObserver", "DEFAULT(" + event + "): " + path);
                break;
        }
    }

    /**
     * Monitor single directory and dispatch all events to its parent, with full path.
     * @author    uestc.Mobius <mobius@toraleap.com>
     * @version  2011.0121
     */
    class SingleFileObserver extends FileObserver {
        String mPath;

        public SingleFileObserver(String path) {
            this(path, ALL_EVENTS);
            mPath = path;
        }

        public SingleFileObserver(String path, int mask) {
            super(path, mask);
            mPath = path;
        }

        @Override
        public void onEvent(int event, String path) {
            String newPath = mPath + "/" + path;
            RecursiveFileObserver.this.onEvent(event, newPath);
        }
    }
}

最佳答案

我对RecursiveFileObserver做了一些更改:

  • 添加成员变量activityactivity 被传递给构造函数。然后,它用于在创建或修改文件时输出 Toast 消息。

  • onEvent() Switch case 中,只要创建新文件或修改现有文件,就会显示 Toast 消息。

您可以按照以下步骤设置文件观察器:

1) 如果您在 Android Studio 中已有项目,请在与 MainActivity.java 文件相同的文件夹/目录中添加一个新的 java 文件。将新类命名为 RecursiveFileObserver。将以下内容复制并粘贴到您的 RecursiveFileObserver.java 文件中。

注意第一行是package com.example.shuwnyuan.barchart;您必须将其替换为您自己的包名称,从 MainActivity.java 文件的第一行获取您的包名称。

// replace this below 1 line with your own package name.
package com.example.shuwnyuan.barchart;

//from   w  w w .j  a  v  a  2s.c  o  m
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import android.app.Activity;
import android.os.FileObserver;
import android.util.Log;
import android.widget.Toast;

/**
 * Enhanced FileObserver to support recursive directory monitoring basically.
 * @author    uestc.Mobius <mobius@toraleap.com>
 * @version  2011.0121
 */
public class RecursiveFileObserver extends FileObserver {
    /** Only modification events */
    public static int CHANGES_ONLY = CREATE | DELETE | CLOSE_WRITE | MOVE_SELF | MOVED_FROM | MOVED_TO;

    List<SingleFileObserver> mObservers;
    String mPath;
    int mMask;
    Activity activity;

    public RecursiveFileObserver(String path, Activity activity) {
        super(path, ALL_EVENTS);
        mPath = path;
        mMask = ALL_EVENTS;

        this.activity = activity;
    }

    public RecursiveFileObserver(String path, int mask, Activity activity) {
        super(path, mask);
        mPath = path;
        mMask = mask;

        this.activity = activity;
    }

    @Override
    public void startWatching() {
        if (mObservers != null) return;

        mObservers = new ArrayList<SingleFileObserver>();
        Stack<String> stack = new Stack<String>();
        stack.push(mPath);

        while (!stack.isEmpty()) {
            String parent = stack.pop();
            mObservers.add(new SingleFileObserver(parent, mMask));
            File path = new File(parent);
            File[] files = path.listFiles();
            if (null == files) continue;

            for (File f : files)
            {
                if (f.isDirectory() && !f.getName().equals(".") && !f.getName().equals("..")) {
                    stack.push(f.getPath());
                }
            }
        }

        for (SingleFileObserver sfo : mObservers) {
            sfo.startWatching();
        }
    }

    @Override
    public void stopWatching() {
        if (mObservers == null) return;

        for (SingleFileObserver sfo : mObservers) {
            sfo.stopWatching();
        }
        mObservers.clear();
        mObservers = null;
    }

    @Override
    public void onEvent(int event, final String path) {
        switch (event)
        {
            case FileObserver.ACCESS:
                Log.i("RecursiveFileObserver", "ACCESS: " + path);
                break;
            case FileObserver.ATTRIB:
                Log.i("RecursiveFileObserver", "ATTRIB: " + path);
                break;
            case FileObserver.CLOSE_NOWRITE:
                Log.i("RecursiveFileObserver", "CLOSE_NOWRITE: " + path);
                break;
            case FileObserver.CLOSE_WRITE:
                Log.i("RecursiveFileObserver", "CLOSE_WRITE: " + path);
                break;
            case FileObserver.CREATE:
                Log.i("RecursiveFileObserver", "CREATE: " + path);

                // show Toast message
                activity.runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(activity, "File created: " + path, Toast.LENGTH_LONG).show();
                    }
                });

                break;
            case FileObserver.DELETE:
                Log.i("RecursiveFileObserver", "DELETE: " + path);
                break;
            case FileObserver.DELETE_SELF:
                Log.i("RecursiveFileObserver", "DELETE_SELF: " + path);
                break;
            case FileObserver.MODIFY:
                Log.i("RecursiveFileObserver", "MODIFY: " + path);

                // show Toast message
                activity.runOnUiThread(new Runnable() {
                    public void run() {
                        Toast.makeText(activity, "File modified: " + path, Toast.LENGTH_LONG).show();
                    }
                });

                break;
            case FileObserver.MOVE_SELF:
                Log.i("RecursiveFileObserver", "MOVE_SELF: " + path);
                break;
            case FileObserver.MOVED_FROM:
                Log.i("RecursiveFileObserver", "MOVED_FROM: " + path);
                break;
            case FileObserver.MOVED_TO:
                Log.i("RecursiveFileObserver", "MOVED_TO: " + path);
                break;
            case FileObserver.OPEN:
                Log.i("RecursiveFileObserver", "OPEN: " + path);
                break;
            default:
                Log.i("RecursiveFileObserver", "DEFAULT(" + event + "): " + path);
                break;
        }
    }

    /**
     * Monitor single directory and dispatch all events to its parent, with full path.
     * @author    uestc.Mobius <mobius@toraleap.com>
     * @version  2011.0121
     */
    class SingleFileObserver extends FileObserver {
        String mPath;

        public SingleFileObserver(String path) {
            this(path, ALL_EVENTS);
            mPath = path;
        }

        public SingleFileObserver(String path, int mask) {
            super(path, mask);
            mPath = path;
        }

        @Override
        public void onEvent(int event, String path) {
            String newPath = mPath + "/" + path;
            RecursiveFileObserver.this.onEvent(event, newPath);
        }
    }
}

2) 我们将监视 Android ExternalStorageDirectory 中的文件更改。为此,我们需要明确要求用户授予文件读/写权限。我们在 MainActivityonCreate 中执行此操作。授予权限后,我们观察文件更改的路径。然后我们写入一个名为“MyTestFile”的文件来测试RecursiveFileObserver。第一次写入时,将创建新文件。之后,如果相同的文件已经存在,则修改该文件。创建或修改文件时将显示Toast消息。

在您的 MainActivity 类中,进行了以下更改:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        .....

        if (Settings.System.canWrite(this) == false) {
            // for first time, request user to grant file permission
            requestPermissions(new String[] {
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE
                }, 3000
            );

        } else {
            // permission is already granted
            // start watching path & write to file for test
            watchPathAndWriteFile();
        }
    }

    .....
    ......

    // This function does 2 things:
    // 1) watch path for files changes using "RecursiveFileObserver"
    // 2) write to a file for testing
    public void watchPathAndWriteFile() {
        // the following path depends on your Android device. On my system, it is: "/storage/emulated/0/"
        String path = Environment.getExternalStorageDirectory().getPath() + "/";
        RecursiveFileObserver observer = new RecursiveFileObserver(path, this);

        // start watching the path
        observer.startWatching();

        // if file "MyTestFile" not exist, new file is created. Else file is modified
        try {
            FileWriter out = new FileWriter(new File(Environment.getExternalStorageDirectory() + "MyTestFile"));
            out.write("my file content for test...");
            out.close();
        } catch (IOException e) {
            android.util.Log.e("writeStringAsFile", "Exception: " + e);
        }
    }

    // in "onCreate", user is prompted to grant file read / write permission
    // this function is invoked automatically after user allowed / denied permission
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 3000: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // user granted permission
                    // start watching for path & write to file for testing.
                    watchPathAndWriteFile();
                } else {
                    // user denied permission
                    android.util.Log.e("Permission", "Denied");
                }

                return;
            }
        }
    }

关于java - 如何使用文件观察器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48675119/

相关文章:

java - 改造预期为 BEGIN_OBJECT,但为 BEGIN_ARRAY

android - 如何解决错误 : getSharedPreferences(String, int) is undefined for the type new View.OnClickListener(){}

java - 显示 <c :forEach> loop 中的值

java - Fortify 警告 - 不受支持的 JVM

java - 检查一个值是否为 0 比直接覆盖它更快吗?

java - Spring:循环依赖,@PostConstruct 和@DependsOn 强加的顺序

java - 使用 GSON 解析没有特定结构的字段的 JSON

java - JSR-303 与 Spring 和 Hibernate 混合错误消息

java - 无法在 Release模式下启动 Activity(使用 proguard-android-optimize 配置)

java - 是否曾经调用过 onUpgrade 方法?