7

I am creating an app that launches an activity as soon as the user presses the power button 3 times. After some research I found out that to do this, first you need to create a service which launches a broadcast receiver to check the screen's on/off status.

Basically I want this to run even when the app is closed. It should start another activity as soon as the power button is pressed 3 or more times.

If you know the solution please give me the complete code or a link to the answer.

I somehow managed to write this code but it is not working:

UpdateService.java

This is the service class I used:

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class UpdateService extends Service {

   BroadcastReceiver mReceiver;

   @Override
   public void onCreate() {
      super.onCreate();
     // register receiver that handles screen on and screen off logic
      IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
      filter.addAction(Intent.ACTION_SCREEN_OFF);
      mReceiver = new MyReceiver();
      registerReceiver(mReceiver, filter);
   }

   @Override
   public void onDestroy() {

      unregisterReceiver(mReceiver);
      Log.i("onDestroy Reciever", "Called");

      super.onDestroy();
   }

   @Override
   public void onStart(Intent intent, int startId) {
      boolean screenOn = intent.getBooleanExtra("screen_state", false);
      if (!screenOn) {
         Log.i("screenON", "Called");
         Toast.makeText(getApplicationContext(), "Awake", Toast.LENGTH_LONG)
            .show();
      } else {
         Log.i("screenOFF", "Called");
         Toast.makeText(getApplicationContext(), "Sleep",
    Toast.LENGTH_LONG)
    .show();
      }
}

@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
 return null;
 }
}

MyReceiver.java

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyReceiver extends BroadcastReceiver {
private boolean screenOff;

@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
    screenOff = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
    screenOff = false;
}
Intent i = new Intent(context, UpdateService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
 }
}

mainfest.xml

<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.SCREEN_OFF"/>
<action android:name="android.intent.action.SCREEN_ON"/>
</intent-filter>
</receiver>
<service android:name=".UpdateService" />

Please also mention if I have to include anything into my mainactivity.java file or the activity to redirect to.

I have used these permissions:

<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Ravi
  • 34,851
  • 21
  • 122
  • 183
  • Is this the correct way or do i have to use another method –  May 09 '14 at 08:20
  • 2
    Please Help i cant get it to work ichecked in background services but the updateservice is not showing up –  May 09 '14 at 08:46

7 Answers7

0

Don't have you complete code to know for sure, but let me make an educated guess:

you didn't implement an Application or Activity yeah?

I think you need at least one of them to register the receiver in onCreate() onResume() callbacks, simply stating a receiver in manifest MIGHT NOT work.

And debugging in eclipse or any other IDE with android integration can be really helpful, since it shows the processes of your app, and you can know for sure whether they are brought up or not. A little debugging shall tell you whether your receiver is working correctly.

if you care to share more code, we can of course discuss further.

zhao chang
  • 211
  • 3
  • 8
  • what do u suggest i should do –  May 10 '14 at 05:45
  • Hook up your code in eclipse and debug ypur receiver? If no luck, try register the receiver programmatically at runtime using an application or activity? – zhao chang May 11 '14 at 07:25
0

Try this?

MyService
public class MyService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();

        ...

        if (!registered) {
            MyReceiver mybroadcast = new MyReceiver() {
            registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON));
            registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF));
        }
    }
}

MyReceiver
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ...
    }
}

BootStartUpReciever
public class BootStartUpReciever extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Start Service On Boot Start Up
        Intent service = new Intent(context, MyService.class);
        context.startService(service);
    }
}



Manifest

<service android:name="my.package.MyService" />
<receiver
    android:name="my.package.BootStartUpReciever" android:enabled="true" android:exported="true" >
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</receiver>
twb
  • 1,248
  • 4
  • 18
  • 31
  • Syntax error or tokkens,misplaced constructur,also have to add on bind method –  May 12 '14 at 07:08
  • 2
    I gave the minimum codes. You do see ...? That is to be replaced by your logic codes. – twb May 12 '14 at 07:10
0

I think there is no need for the service class for your requirement. Because you're going to start a activity when screen on action is called. Kindly refer my below implementation and share your thoughts.

//Application class.
    public class MyApplication extends Application {
        static String TAG = "MyApplication";
        @Override
        public void onCreate() {
            super.onCreate();

            IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
            intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
            registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    // screen off
                    if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                        Log.d(TAG, Intent.ACTION_SCREEN_OFF);
                        //screen on
                    } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                        Log.d(TAG, Intent.ACTION_SCREEN_ON);
                        // To open your main activity.
                        Intent i = new Intent();
                        i.setClass(context, MainActivity.class);
                        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(i);
                    }
                }
            }, intentFilter);
        }

    }

    // Manifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.hopabit.wakeup"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="19" />

        <application
            android:name=".MyApplication"
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.hopabit.wakeup.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>
Rajiv Manivannan
  • 504
  • 7
  • 15
0

In order to keep your service running you need to put into a thread. Make sure that the service is in an extra thread, because a service for itself is not a extra process or thread. This could be done, for example with an Handler.

HandlerThread thread = new HandlerThread(SERVICE_THREAD_NAME);
thread.start();
handlerThreadId = thread.getId();
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
danilodeveloper
  • 3,840
  • 2
  • 36
  • 56
0

I saw your code. You are very near to the solution.

register your broad cast receiver for both events screen off as well as screen on inside the onCreate() of you Activity

if (!registered) {
            MyReceiver mybroadcast = new MyReceiver() {
            registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON));
            registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF));
}

Maintain a int counter in shared preference or any where else, initialized it with 0 at first and increment that counter in onReceive():

public class MyReceiver extends BroadcastReceiver {
private boolean screenOff;

@Override
public void onReceive(Context context, Intent intent) {

int counter = get counter value from shared preference.

if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
    screenOff = true;
    //increment the counter++

} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
    screenOff = false;
    //increment the counter++
}

if(counter>3){
Intent i = new Intent(context, UpdateService.class);
i.putExtra("screen_state", screenOff);
context.startService(i);
}
 }
}
MohammedYakub M.
  • 2,893
  • 5
  • 31
  • 42
0

You can start service and repeating it frequently and also listen event on Boot. You can use this link which has a service running all the time. https://github.com/commonsguy/cwac-wakeful It could help in your problem.

Manmohan Badaya
  • 2,326
  • 1
  • 22
  • 35
0

I think what you need is to use an IntentService.

I will tell you why:

Service are running on the UI Thread (even when are on background), so this is better for interaction with the UI, but on the other hand, they shouldn't be running for long period of time like you want. Aside, the IntentService are running on another Thread, so it is better to use them for background tasks which are longer.

What you should do is to save on memory (using the Application object) or another Singleton the times the screen ON/OFF status.

If you need more help, just let me know

zapotec
  • 2,628
  • 4
  • 31
  • 53