专栏首页蜉蝣禅修之道Android之本地文件夹实时检测与上传服务实现

Android之本地文件夹实时检测与上传服务实现

好久都没有更新博客了,这期的功能是实现本地文件夹的监测和上传文件到阿里的OSS服务器上,由于这个功能不需要界面而且需要程序退到后台时依然监测,所以初步定为用服务实现。

首先,第一个需要确定能否用IntentService实现呢,因为IntentService会自动创建新的线程,只允许startService启动,而且消息队列也帮我们管理了,省了很多功夫,但是IntentService会自动停止服务,似乎不适合我们的业务需求,因此,我们需要自己创建线程和管理消息队列了,所以首先上服务基础类的代码。注意,我们只允许startService启动服务,因为该service不是随调用者停止而停止的。

import android.app.Service;
import android.content.Intent;
import android.os.*;

public abstract class BaseService extends Service {

    abstract protected void onWorkerRequest(Message msg);

    @Override
    public void onStart(Intent intent, int startId) {
        handleStart(intent, startId);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        handleStart(intent, startId);
        return START_NOT_STICKY;
    }

    abstract protected void handleStart(Intent intent, int startId);

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    protected final class WorkerHandler extends Handler {
        public WorkerHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onWorkerRequest(msg);
        }
    }

    protected HandlerThread mWorker = null;
    protected WorkerHandler mHandler = null;

    protected void startWorker(String tag) {
        if (mWorker == null) {
            mWorker = null;
            mWorker = new HandlerThread(tag);
            mWorker.start();
            mHandler = null;
            mHandler = new WorkerHandler(mWorker.getLooper());
        } else if (mWorker.getState() == Thread.State.NEW) {
            mWorker.start();
            mHandler = null;
            mHandler = new WorkerHandler(mWorker.getLooper());
        } else if (mWorker.getState() == Thread.State.WAITING) {
            mHandler = null;
            mHandler = new WorkerHandler(mWorker.getLooper());
        } else if (mWorker.getState() == Thread.State.TERMINATED) {
            mWorker = null;
            mWorker = new HandlerThread(tag);
            mWorker.start();
            mHandler = null;
            mHandler = new WorkerHandler(mWorker.getLooper());
        }
    }

    protected void endWorker() {
        mHandler = null;
        HandlerThread snap = mWorker;
        mWorker = null;
        snap.quit();
        snap.interrupt();
    }

    protected WorkerHandler getWorkerHandler() {
        return mHandler;
    }

}

进一步简化

import android.content.Intent;
import android.os.Message;
import android.util.Log;
import com.aibasis.xlsdk.util.PermissionManager;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public abstract class BaseWorkerService extends BaseService {

	private final Lock mWorkerLock = new ReentrantLock();

	public abstract String getWorkerTag();
	public abstract void onWorkerRequest(Intent intent, int startId);

	@Override
	public void onCreate() {
		super.onCreate();

		startWorker(getWorkerTag());
	}

	@Override
	protected void handleStart(Intent intent, int startId) {
		try {
			Message msg = getWorkerHandler().obtainMessage();
			msg.what = startId;
			msg.obj = intent;
			getWorkerHandler().dispatchMessage(msg);
		} catch (Exception e) {
			Log.e("WorkerService", e.getMessage());
		}
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		endWorker();
	}

	@Override
	protected void onWorkerRequest(Message msg) {
		mWorkerLock.lock();
		PermissionManager.getWakeLockInstance(this, getWorkerTag()).acquire();
		try {
			onWorkerRequest((Intent) msg.obj, msg.what);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			PermissionManager.getWakeLockInstance(this, getWorkerTag()).release();
			mWorkerLock.unlock();
		}
	}
}

OK,实现完基础服务类,我们可以关注业务需求了,监测文件夹文件创建事件可用FileObserver,代码如下:

import android.content.Intent;
import android.os.FileObserver;
import android.util.Log;
import com.aibasis.xlsdk.log.LogWorker;
import com.aibasis.xlsdk.util.Config;
import com.aibasis.xlsdk.util.Oss;
import com.aibasis.xlsdk.util.NetworkUtil;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.callback.OSSCompletedCallback;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;

import java.io.File;

public class RecordUploadService extends BaseWorkerService {
    private String TAG = getClass().getCanonicalName();
    public static final String ACTION_UPLOAD = "ACTION_UPLOAD";
    private RecordFileListener recordFileListener = null;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public String getWorkerTag() {
        return RecordUploadService.class.getSimpleName();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (recordFileListener != null)
            recordFileListener.stopWatching();
    }

    @Override
    public void onWorkerRequest(Intent intent, int startId) {
        Log.d(TAG, "receive Request");
        if (ACTION_UPLOAD.equals(intent.getAction())) {
            String observeDir = Config.AUDIO_DIR;
//            String remoteDir = intent.getStringExtra("remoteDir");
            if (recordFileListener != null) {
                recordFileListener.stopWatching();
                recordFileListener = null;
            }
            recordFileListener = new RecordFileListener(observeDir);
            recordFileListener.startWatching();
            Log.d(TAG, "start watching directory " + observeDir);
        }
    }

    private class RecordFileListener extends FileObserver {
        private String recordDirName;
//        private String remoteDir;

        public RecordFileListener(String path) {
            super(path);
            recordDirName = path;
//            this.remoteDir = remoteDir;
        }

        @Override
        public void onEvent(int event, String path) {
            switch (event) {
                case FileObserver.CREATE:
                    Log.d(TAG, "Record has been created: " + path);
                    // 如果wifi连通,上传至OSS服务器
                    if (NetworkUtil.getInstance().isWifiConnected(RecordUploadService.this)) {
                        File recordDir = new File(recordDirName);
                        if (recordDir.exists() && recordDir.isDirectory()) {
                            for (File file : recordDir.listFiles()) {
                                upload(file);
                            }
                        }
                    }
                    break;
            }
        }
    }
}

好了,所有功能都已实现,服务看上去很强大,但对于用户来说却是有些流氓,因为可以一直在后台监控用户,唉~

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++简单实现八皇后问题

    forrestlin
  • Android禁止横屏竖屏切换

    forrestlin
  • ListView不能响应itemclick事件的解决方法

    forrestlin
  • 【Android】实现ImageView的展示网络图片的功能

    无道
  • Spring Boot:实现MyBatis动态创建表

    在有些应用场景中,我们会有需要动态创建和操作表的需求。比如因为单表数据存储量太大而采取分表存储的情况,又或者是按日期生成日志表存储系统日志等等。这个时候就需要我...

    朝雨忆轻尘
  • 安卓开发_浅谈TimePicker(时间选择器)

    听着music睡
  • EasyExcel 筛选和冻结固定表头

    我的原回答: https://github.com/alibaba/easyexcel/issues/874

    林万程
  • MyBatis注解开发

    指的是MyBatis中SqlSession对象的缓存,当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。

    用户3112896
  • 16.语音识别

    六月的雨
  • Android 系统缓存扫描与清理方法分析

    本文讲述内容的完整代码实例见 https://github.com/mzlogin/CleanExpert。

    mzlogin

扫码关注云+社区

领取腾讯云代金券