ClipboardMonitor.java :  » UnTagged » my-clips » com » myclips » service » Android Open Source

Android Open Source » UnTagged » my clips 
my clips » com » myclips » service » ClipboardMonitor.java
package com.myclips.service;

import java.util.HashSet;
import java.util.Set;

import com.myclips.LogTag;
import com.myclips.MyClips;
import com.myclips.R;
import com.myclips.db.Clip;
import com.myclips.db.ClipboardDbAdapter;
import com.myclips.prefs.AppPrefs;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.FileObserver;
import android.os.IBinder;
import android.text.ClipboardManager;
import android.util.Log;

/**
 * Starts a background thread to monitor the states of clipboard and stores
 * any new clips into the SQLite database.
 * <p>
 * <i>Note:</i> the current android clipboard system service only supports
 * text clips, so in browser, we can just save images to external storage
 * (SD card). This service also monitors the downloads of browser, if any
 * image is detected, it will be stored into SQLite database, too.   
 */
public class ClipboardMonitor extends Service implements LogTag {
    
    /** Image type to be monitored */
    private static final String[] IMAGE_SUFFIXS = new String[] {
        ".jpg", ".jpeg", ".gif", ".png"
    };
    /** Path to browser downloads */
    private static final String BROWSER_DOWNLOAD_PATH = "/sdcard/download";
    
    private NotificationManager mNM;
    private MonitorTask mTask = new MonitorTask();
    private ClipboardManager mCM;
    private ClipboardDbAdapter mDbAdapter;
    private SharedPreferences mPrefs;

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

    @Override
    public void onCreate() {
        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        showNotification();
        mCM = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
        mDbAdapter = new ClipboardDbAdapter(this);
        mPrefs = getSharedPreferences(AppPrefs.NAME, MODE_PRIVATE);
        AppPrefs.operatingClipboardId = mPrefs.getInt(
                AppPrefs.KEY_OPERATING_CLIPBOARD,
                AppPrefs.DEF_OPERATING_CLIPBOARD);
        mTask.start();
    }

    private void showNotification() {
        Notification notif = new Notification(R.drawable.myclips_icon,
                "MyClips clipboard monitor is started",
                System.currentTimeMillis());
        notif.flags |= (Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, MyClips.class), 0);
        notif.setLatestEventInfo(this, getText(R.string.clip_monitor_service),
                "Tap here to enter MyClips UI", contentIntent);
        // Use layout id because it's unique
        mNM.notify(R.string.clip_monitor_service, notif);
    }
    
    @Override
    public void onDestroy() {
        mNM.cancel(R.string.clip_monitor_service);
        mTask.cancel();
        mDbAdapter.close();
    }
    
    @Override
    public void onStart(Intent intent, int startId) {
    }

    /**
     * Monitor task: monitor new text clips in global system clipboard and
     * new image clips in browser download directory
     */
    private class MonitorTask extends Thread {

        private volatile boolean mKeepRunning = false;
        private String mOldClip = null;
        private BrowserDownloadMonitor mBDM = new BrowserDownloadMonitor();
        
        public MonitorTask() {
            super("ClipboardMonitor");
        }

        /** Cancel task */
        public void cancel() {
            mKeepRunning = false;
            interrupt();
        }
        
        @Override
        public void run() {
            mKeepRunning = true;
            mBDM.startWatching();
            while (true) {
                doTask();
                try {
                    Thread.sleep(mPrefs.getInt(AppPrefs.KEY_MONITOR_INTERVAL,
                            AppPrefs.DEF_MONITOR_INTERVAL));
                } catch (InterruptedException ignored) {
                }
                if (!mKeepRunning) {
                    break;
                }
            }
            mBDM.stopWatching();
        }
        
        private void doTask() {
            if (mCM.hasText()) {
                String newClip = mCM.getText().toString();
                if (!newClip.equals(mOldClip)) {
                    Log.i(TAG, "detect new text clip: " + newClip.toString());
                    mOldClip = newClip;
                    mDbAdapter.insertClip(Clip.CLIP_TYPE_TEXT,
                            newClip.toString(),
                            AppPrefs.operatingClipboardId);
                            //mPrefs.getInt(AppPrefs.KEY_OPERATING_CLIPBOARD,
                            //        AppPrefs.DEF_OPERATING_CLIPBOARD));
                    Log.i(TAG, "new text clip inserted: " + newClip.toString());
                }
            }
        }
        
        /**
         * Monitor change of download directory of browser. It listens two
         * events: <tt>CREATE</tt> and <tt>CLOSE_WRITE</tt>. <tt>CREATE</tt>
         * event occurs when new file created in download directory. If this
         * file is image, new image clip will be inserted into database when 
         * receiving <tt>CLOSE_WRITE</tt> event, meaning file is sucessfully
         * downloaded.
         */
        private class BrowserDownloadMonitor extends FileObserver {

            private Set<String> mFiles = new HashSet<String>();
            
            public BrowserDownloadMonitor() {
                super(BROWSER_DOWNLOAD_PATH, CREATE | CLOSE_WRITE);
            }
            
            private void doDownloadCompleteAction(String path) {
                mDbAdapter.insertClip(Clip.CLIP_TYPE_IMAGE,
                        BROWSER_DOWNLOAD_PATH + "/" + path,
                        AppPrefs.operatingClipboardId);
                        //mPrefs.getInt(AppPrefs.KEY_OPERATING_CLIPBOARD,
                        //        AppPrefs.DEF_OPERATING_CLIPBOARD));
                Log.i(TAG, "new image clip inserted: " + path);
            }
            
            @Override
            public void onEvent(int event, String path) {
                switch (event) {
                    case CREATE:
                        for (String s : IMAGE_SUFFIXS) {
                            if (path.endsWith(s)) {
                                Log.i(TAG, "detect new image: " + path);
                                mFiles.add(path);
                                break;
                            }
                        }
                        break;
                    case CLOSE_WRITE:
                        if (mFiles.remove(path)) { // File download completes
                            doDownloadCompleteAction(path);
                        }
                        break;
                    default:
                        Log.w(TAG, "BrowserDownloadMonitor go unexpected event: "
                                + Integer.toHexString(event));                        
//                        throw new RuntimeException("BrowserDownloadMonitor" +
//                            " got unexpected event");
                }
            }
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.