Search code examples
androidservicescreensaveruser-inactivity

How to achieve Android ScreenSaver via service or application


After some research, I concluded there is nth like screen saver in androd. But there are some similar like Live-Wallpapers in Launcher screen or lock Screen.

I attempted a small wayout using service.

In my Activity after inactive for certain time I started a service.

My service started twice after the inactivity.

I want the service start once and as well whole over my app.How to do that?

Here are the codes I used.

User Inactive:

serviceHandler = new Handler();
serviceRunnable = new Runnable() {
    @Override
    public void run() {
        Log.e("run times","Myservice");
        startService(new Intent(getBaseContext(), MyService.class));
        serviceHandler.removeCallbacks(serviceRunnable);
    }
};
@Override
public void onUserInteraction() {
    super.onUserInteraction();
    serviceHandler.removeCallbacks(serviceRunnable);
    stopService(new Intent(getBaseContext(), MyService.class));
    serviceHandler.postDelayed(serviceRunnable, 8000);
}

MyService:

public class MyService extends Service {

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(MyService.this, "Service Started", Toast.LENGTH_SHORT).show();

        ArrayList<String> imagelist = new ArrayList<>();
        imagelist.add("");

        Intent i = new Intent(this, ScreenSaverActivity.class);
        i.putExtra("imageList", imagelist);
        i.putExtra("delay", 3000);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(i);


        return START_STICKY;
    }


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

    }


}

ScreenSaver Activity is:

public class ScreenSaverActivity extends Activity {
    ImageView imgScreenSaver;
    LinearLayout screenSaverLayout;
    Handler screenSaverHandler;
    Runnable screenSaverRunnable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_saver);
        screenSaverLayout = (LinearLayout) findViewById(R.id.layout_screen_saver);
        imgScreenSaver = (ImageView) findViewById(R.id.img_screenSaver);
        Bundle bundle = getIntent().getExtras();
        repeatScreenSaver(bundle.getStringArrayList("imageList"), bundle.getInt("delay"));
//        repeatScreenSaver("",bundle.getInt("delay"));
    }

    private void repeatScreenSaver(final ArrayList<String> imageList, final int milliseconds) {

        screenSaverHandler = new Handler();
        screenSaverRunnable = new Runnable() {
            @Override
            public void run() {
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imgScreenSaver.getLayoutParams());
                Random random = new Random();

                params.setMargins(random.nextInt(500), random.nextInt(500),
                        random.nextInt(200), random.nextInt(200));
                imgScreenSaver.setLayoutParams(params);
                Ion.with(ScreenSaverActivity.this)
                        .load(imageList.get(
                                        new Random().nextInt(imageList.size()
                                        )
                                )
                        )
                        .withBitmap()
                        .error(R.mipmap.ic_launcher)
                        .intoImageView(imgScreenSaver);
                screenSaverHandler.postDelayed(this, milliseconds);

            }
        };
        screenSaverHandler.postDelayed(screenSaverRunnable, milliseconds);
    }



    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        screenSaverHandler.removeCallbacks(screenSaverRunnable);
        finish();
        return super.onKeyDown(keyCode, event);
    }

And the screensaver layout is:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/layout_screen_saver"
    android:background="#a0000000">
    <ImageView
        android:id="@+id/img_screenSaver"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

I've added following code in manifest:

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

as MyService is inside the package .service


Solution

  • I couldn't find any reliable answer but I got my solution within the application itself using reference to many answers for userInactivity, use of Application.class, currentAppInForeground() and many others. I've included the whole project for screenSaver itself here.

    I used Application.class for it.

    Here I first found a user inactivity via a thread which runs in Application.class Then I kept a condition to show screen saver i.e

    if(applicationIsInForeGround() && !screenSaverActive && !videoPlaying){
        // start screen saver activity
    }
    

    The main drawback here is the thread runs even if the app is closed. It might stop when the app is force stopped or device is restarted or the app is uninstalled.