Monitor File and Directory changes with Apache Commons IO

FileAlterationObserver observer = new FileAlterationObserver("pathToDir");
FileAlterationMonitor monitor = new FileAlterationMonitor(POLL_INTERVAL);
FileAlterationListener listener = new FileAlterationListenerAdaptor() {
    @Override
    public void onFileCreate(File file) {
        // code for processing creation event
    }
 
    @Override
    public void onFileDelete(File file) {
        // code for processing deletion event
    }
 
    @Override
    public void onFileChange(File file) {
        // code for processing change event
    }
};
observer.addListener(listener);
monitor.addObserver(observer);
monitor.start();

References
http://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library

Start Sticky Service on Boot in Android

BroadcastReceiverOnBootComplete.java

public class BroadcastReceiverOnBootComplete extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED)) {
            Intent serviceIntent = new Intent(context, AndroidServiceStartOnBoot.class);
            context.startService(serviceIntent);
        }
    }
}

AndroidServiceStartOnBoot.java

public class AndroidServiceStartOnBoot extends Service {

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

    @Override
    public void onCreate() {
        super.onCreate();
       // here you can add whatever you want this service to do
    }

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javacodegeeks.androidserviceonbootexample">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>

    <receiver
        android:name="com.javacodegeeks.androidserviceonbootexample.BroadcastReceiverOnBootComplete"
        android:enabled="true"
        android:exported="false">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.PACKAGE_REPLACED" />
            <data android:scheme="package" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.PACKAGE_ADDED" />
            <data android:scheme="package" />
        </intent-filter>
    </receiver>

    <service android:name="com.javacodegeeks.androidserviceonbootexample.AndroidServiceStartOnBoot"></service>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <activity
            android:name="com.javacodegeeks.androidserviceonbootexample.MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest
>

if we want to be sure our service is sticky

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        if (workerThread == null) {
            workerThread = Thread(run)
            workerThread!!.start()

            Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
        }

        return Service.START_STICKY
    }

and

    override fun onTaskRemoved(rootIntent: Intent?) {
        val restartService = Intent(applicationContext,
                this.javaClass)
        restartService.`package` = packageName
        val restartServicePI = PendingIntent.getService(
                applicationContext, 1, restartService,
                PendingIntent.FLAG_ONE_SHOT)
        val alarmService = applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 5000, restartServicePI)
    }

References
http://blog.vogella.com/2011/12/11/automatically-starting-services-in-android-after-booting/
https://examples.javacodegeeks.com/android/core/activity/android-start-service-boot-example/
http://www.framentos.com/en/android-tutorial/2012/08/01/how-to-start-a-service-at-boot-in-android/

Working with FileObserver on Android

private class PathFileObserver extends FileObserver{
        static final String TAG="FILEOBSERVER";
        /**
         * should be end with File.separator
         */
    	String rootPath;
    	static final int mask = (FileObserver.CREATE | 
    			FileObserver.DELETE | 
    			FileObserver.DELETE_SELF |
    			FileObserver.MODIFY |
    			FileObserver.MOVED_FROM |
    			FileObserver.MOVED_TO |
    			FileObserver.MOVE_SELF); 
    	
    	public PathFileObserver(String root){
    		super(root, mask);

    		if (! root.endsWith(File.separator)){
    			root += File.separator;
    		}
    		rootPath = root;
    	}

    	public void onEvent(int event, String path) {
    		
    		switch(event){
    		case FileObserver.CREATE:
    			Log.d(TAG, "CREATE:" + rootPath + path);
    			break;
    		case FileObserver.DELETE:
    			Log.d(TAG, "DELETE:" + rootPath + path);
    			break;
    		case FileObserver.DELETE_SELF:
    			Log.d(TAG, "DELETE_SELF:" + rootPath + path);
    			break;
    		case FileObserver.MODIFY:
    			Log.d(TAG, "MODIFY:" + rootPath + path);
    			break;
    		case FileObserver.MOVED_FROM:
    			Log.d(TAG, "MOVED_FROM:" + rootPath + path);
    			break;
    		case FileObserver.MOVED_TO:
    			Log.d(TAG, "MOVED_TO:" + path);
    			break;
    		case FileObserver.MOVE_SELF:
    			Log.d(TAG, "MOVE_SELF:" + path);
    			break;
    		default:
    			// just ignore
    			break;
    		}
    	}

    	public void close(){
    		super.finalize();
    	}
    }

References
https://gist.github.com/shirou/659180

Create a Bound Service on Android

AndroidManifest.xml

<service android:name=".MyService"/>

MyService.java

public class MyService extends Service {

    Binder mBinder = new LocalService();

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


    public class LocalService extends Binder {

        MyService getService() {
            return MyService.this;
        }

    }

    public String getFirstMessage() {
        return "Message 1";
    }

    public String getSecondMessage() {
        return "Message 2";
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    MyService myService = null;

    Button buttonMessage1;
    Button buttonMessage2;
    TextView textViewOutput;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent(MainActivity.this, MyService.class);
        bindService(intent, serviceConnection, BIND_AUTO_CREATE);

        buttonMessage1 = (Button) findViewById(R.id.buttonMessage1);
        buttonMessage2 = (Button) findViewById(R.id.buttonMessage2);
        textViewOutput = (TextView) findViewById(R.id.textViewOutput);

        buttonMessage1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (myService != null) {
                    textViewOutput.setText(myService.getFirstMessage());
                }
            }
        });

        buttonMessage2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (myService != null) {
                    textViewOutput.setText(myService.getSecondMessage());
                }
            }
        });
    }

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            MyService.LocalService localService = (MyService.LocalService) iBinder;
            myService = localService.getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            myService = null;
        }
    };

    @Override
    protected void onStop() {
        super.onStop();

        unbindService(serviceConnection);
        myService = null;
    }
}

References
https://www.youtube.com/watch?v=PUxC6vzEEgg
https://github.com/mhdr/AndroidSamples/tree/master/101

Service Using IntentService on Android

public class MyService extends IntentService {

    int counter = 0;

    public MyService() {
        super("MyServiceThread");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

        counter++;
        Handler handler = new Handler(getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MyService.this, "Service Stared: " + counter, Toast.LENGTH_SHORT).show();
            }
        });

        for (int i = 0; i < 10; i++) {
            try {
                wait(1500);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void onDestroy() {
        Toast.makeText(MyService.this, "Service Stopped", Toast.LENGTH_SHORT).show();
    }
}

References
https://www.youtube.com/watch?v=cpq163QF2nM
https://github.com/mhdr/AndroidSamples/tree/master/100

Using Thread in Android Service

MyService.java

public class MyService extends Service {

    Thread workerThread = null;
    int counter=0;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        final Handler handler = new Handler(getMainLooper());

        synchronized (this) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {

                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            counter++;
                            Toast.makeText(MyService.this, "Service Started: " + counter, Toast.LENGTH_SHORT).show();
                        }
                    });


                    for (int i = 0; i < 10; i++) {
                        try {
                            wait(1500);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            };

            if (workerThread == null) {
                workerThread = new Thread(runnable);
                workerThread.start();
            }
        }

        return Service.START_STICKY;
    }


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

        if (workerThread != null) {
            workerThread.interrupt();
            workerThread = null;
            Toast.makeText(MyService.this, "Service Stopped", Toast.LENGTH_SHORT).show();
        }

    }

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

AndroidManifest.xml

<service android:name=".MyService" />

MainActivity.java

public class MainActivity extends AppCompatActivity {

    Button buttonStartService;
    Button buttonStopService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        buttonStartService = (Button) findViewById(R.id.buttonStartService);
        buttonStopService = (Button) findViewById(R.id.buttonStopService);

        buttonStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                startService(intent);
            }
        });

        buttonStopService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                stopService(intent);
            }
        });
    }
}

References
https://www.youtube.com/watch?v=foGmyYe2bV8
https://github.com/mhdr/AndroidSamples/tree/master/099

Running code in Main thread from another thread using Handler

runOnUiThread() will execute the Runnable immediately. but post() always puts the Runnable at the end of the event queue, even if you are already on the main application thread

// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(context.getMainLooper());

Runnable myRunnable = new Runnable() {
    @Override 
    public void run() {....} // This is your code
};
mainHandler.post(myRunnable);
MainActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

References
https://stackoverflow.com/questions/11123621/running-code-in-main-thread-from-another-thread
https://stackoverflow.com/questions/12850143/android-basics-running-code-in-the-ui-thread

Create a Started Service on Android

MyService.java

public class MyService extends Service {

    private int counter=0;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        counter++;

        Toast.makeText(this, "Service Started : " + counter, Toast.LENGTH_SHORT).show();

        return Service.START_STICKY;
    }

    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service Stopped", Toast.LENGTH_SHORT).show();
    }

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

MainActivity.java

public class MainActivity extends AppCompatActivity {


    Button buttonStartService;
    Button buttonStopService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        buttonStartService = (Button) findViewById(R.id.buttonStartService);
        buttonStopService = (Button) findViewById(R.id.buttonStopService);

        buttonStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                startService(intent);
            }
        });

        buttonStopService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MyService.class);
                stopService(intent);
            }
        });
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="pupli.net.a098">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".MyService" />
    </application>

</manifest>

References
https://www.youtube.com/watch?v=HYctmRwYHOg
https://github.com/mhdr/AndroidSamples/tree/master/098