Since your Activity doesn't persist after the app is killed, you must go for a Service class. There're some circumstances where it may also be killed, but in a normal basis it will persist in most cases (otherwise check foreground services).
This approach should work:
Java
public class TestClipboardServiceActivity extends Activity {
@Override protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startService(new Intent(this, MyClipboardService.class));
// Forced the app to be destroyed intentionally.
finish();
}
}
/**
* Clipboard Service. It will clear the clipboard after 60 seconds.
*/
public class MyClipboardService extends Service {
public class LocalBinder extends Binder {
MyClipboardService getService() {
return MyClipboardService.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyClipboardService", "Received start id " + startId + ": " + intent);
// Remember, this is executed in the main thread.
new Handler().postDelayed(new Runnable() {
@Override public void run() {
clearClipboard();
}
}, 6000);
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private final IBinder mBinder = new LocalBinder();
/**
* Clears the clipboard.
*/
private void clearClipboard() {
ClipboardManager myClipboard =
(ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
if (myClipboard != null) {
myClipboard.setPrimaryClip(ClipData.newPlainText(null, "");
}
}
}
Kotlin
class TestClipboardServiceActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startService(Intent(this, MyClipboardService::class.java))
// Forced the app to be destroyed intentionally.
finish()
}
}
/**
* Clipboard Service. It will clear the clipboard after 60 seconds.
*/
class MyClipboardService : Service() {
private val mBinder = LocalBinder()
inner class LocalBinder : Binder() {
internal val service: MyClipboardService
get() = this@MyClipboardService
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
Log.i("MyClipboardService", "Received start id $startId: $intent")
// Remember, this is executed in the main thread.
Handler().postDelayed(this::clearClipboard, 60000)
return START_STICKY
}
override fun onBind(intent: Intent) = mBinder
/**
* Clears the clipboard.
*/
private fun clearClipboard() {
val myClipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
myClipboard.primaryClip = ClipData.newPlainText(null, "")
}
}
On the other hand, if you prefer to use a custom library to handle jobs, I'll strongly suggest android-job from Evernote. It internally even uses the recent WorkManager
class and the library contains several scheduling variants, apart from compatibility for many Android API and the lack of Google Play Services library. In your case you could take a look at the setExact(long exactInMs) method, providing an offset when the job should run from when the job was scheduled.