1

I am detecting screen on /off time when app is open or close

Using Services and Broadcast Receiver. it is working good when app is running or minimizing but during closing app it is going crashed.

How to get screen on/off time once close the app without crash .

Error in logcat

E/ActivityThread: Activity com.shah.neeraj.s.MainActivity has leaked IntentReceiver com.shah.neeraj.s.ScreeReceiver@8686ff5 that was originally registered here. Are you missing a call to unregisterReceiver()?
                  android.app.IntentReceiverLeaked: Activity com.shah.neeraj.s.MainActivity has leaked IntentReceiver com.shah.neeraj.s.ScreeReceiver@8686ff5 that was originally registered here. Are you missing a call to unregisterReceiver()?
                      at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1159)
                      at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:946)
                      at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1330)
                      at android.app.ContextImpl.registerReceiver(ContextImpl.java:1310)
                      at android.app.ContextImpl.registerReceiver(ContextImpl.java:1304)
                      at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:586)
                      at com.shah.neeraj.s.MainActivity.onCreate(MainActivity.java:37)
                      at android.app.Activity.performCreate(Activity.java:6672)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1140)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2612)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2724)
                      at android.app.ActivityThread.-wrap12(ActivityThread.java)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1473)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6123)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
Application terminated.

MainActivity

public class MainActivity extends Activity {
    TextView text1,text2,text3;   
    Date d,d1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        text1 = (TextView) findViewById(R.id.text1);
        text2 = (TextView) findViewById(R.id.text2);
        text3 =(TextView) findViewById(R.id.text3);    

        // INITIALIZE RECEIVER
       IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        BroadcastReceiver mReceiver = new ScreeReceiver();
        registerReceiver(mReceiver, filter);
//        unregisterReceiver(mReceiver);
        PowerManager pm =(PowerManager) getSystemService(Context.POWER_SERVICE);
        // YOUR CODE
    }

    @Override
    protected void onPause() {
        // WHEN THE SCREEN IS ABOUT TO TURN OFF
        if (ScreeReceiver.wasScreenOn)
        {
        //if (pm.isScreenOn() == false){
            // THIS IS THE CASE WHEN ONPAUSE() IS CALLED BY THE SYSTEM DUE TO A SCREEN STATE CHANGE

            d = new Date();
            CharSequence s = DateFormat.format("hh:mm:ss", d.getTime());

            System.out.println("SCREEN TURNED OFF");
            text1.setText("SCREEN TURNED OFF" + s);
            Log.i("hi", "s"+ s);  
        } else {
            // THIS IS WHEN ONPAUSE() IS CALLED WHEN THE SCREEN STATE HAS NOT CHANGED
        }
        super.onPause();    
    }

    @Override
    protected void onResume() {
        // ONLY WHEN SCREEN TURNS ON
        if (!ScreeReceiver.wasScreenOn) {
            // THIS IS WHEN ONRESUME() IS CALLED DUE TO A SCREEN STATE CHANGE

            d1 = new Date();
            CharSequence s1 = DateFormat.format("hh:mm:ss", d1.getTime());

            text2.setText("SCREEN TURNED ON" + s1);
            Log.i("hi", "s"+ s1);

            System.out.println("SCREEN TURNED ON");

            Timer updateTimer = new Timer();
            updateTimer.schedule(new TimerTask()
            {    
                public void run()
                {
                    try
                    {    
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {    
                                //stuff that updates ui
                                long diff = d1.getTime() - d.getTime();

                                int Hours = (int) (diff/( 1000* 60 * 60));
                                int Mins = (int) (diff/(1000*60)) % 60;

                                Log.i("Difference ", ""+ diff);

                                String diff1= Hours + ":" + Mins; // updated value every 60 second
                                text3.setText( diff1 );
                                Log.i("Differ", "diff"+ diff1);
                            }
                        });    
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }    
            }, 0, 600000);    
        } else {
        }
        super.onResume();  
    }    

    @Override
    public void onDestroy() {
        super.onDestroy();
        //Log.d(msg, "The onDestroy() event");
        /*IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        BroadcastReceiver mReceiver = new ScreeReceiver();
        unregisterReceiver(mReceive);*/    
    }
}

ScreenReceiver

public class ScreeReceiver extends BroadcastReceiver {
    public static boolean wasScreenOn = true;
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            // DO WHATEVER YOU NEED TO DO HERE
            wasScreenOn = false;
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            // AND DO WHATEVER YOU NEED TO DO HERE
            wasScreenOn = true;
        }
        Intent i = new Intent(context, UpdateService.class);
        i.putExtra("screen_state", wasScreenOn);
        context.startService(i);

        Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
    }    
}

UpdateService

public class UpdateService extends Service {
    TextView text1,text2,text3;
    @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);
        BroadcastReceiver mReceiver = new ScreeReceiver();
        registerReceiver(mReceiver, filter);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        boolean screenOn = intent.getBooleanExtra("screen_state", false);
        if (!screenOn) {
           // YOUR CODE
            /* Date d = new Date();
            CharSequence s = DateFormat.format("hh:mm:ss", d.getTime());

            System.out.println("SCREEN TURNED OFF");
            text1.setText("SCREEN TURNED OFF" + s);
            Log.i("hi", "s"+ s);
            */
            Date d = new Date();
            CharSequence s = DateFormat.format("hh:mm:ss", d.getTime());

            System.out.println("SCREEN TURNED OFF");
            Log.i("hi Service t off", "s"+ s);

           // text1.setText("SCREEN TURNED OFF" + s);
            System.out.println("SCREEN  Off"+s);

        } else {
            // YOUR CODE
            Date  d1 = new Date();
            CharSequence s1 = DateFormat.format("hh:mm:ss", d1.getTime());

            //text2.setText("SCREEN TURNED ON" + s1);
            Log.i("hi Service t on ", "s"+ s1);

            System.out.println("SCREEN  ON"+s1);
        }
    }

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


    @Override
    public void onDestroy() {
        IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        BroadcastReceiver mReceiver = new ScreeReceiver();
        unregisterReceiver(mReceiver);
    }

Manifest

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        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>

       <receiver android:name="ScreeReceiver">

           <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">

        </service>
    </application>

</manifest>
GoRoS
  • 5,183
  • 2
  • 43
  • 66
Jacks
  • 51
  • 8

3 Answers3

3

Whats your Logcat returns

that was originally registered here. Are you missing a call to unregisterReceiver()?

At first, Declare BroadcastReceiver as Global & You should call below in onPause() Method

And open this onCreate() section .

unregisterReceiver(mReceive);

Finally

 @Override
protected void onStop()
{    ........................
    unregisterReceiver(mReceive);
    super.onStop();
}
IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
  • once done in onPause() app is crashed Caused by: java.lang.IllegalArgumentException: Receiver not registered: com.shah.neeraj.s.ScreeReceiver@a9d1671 at android.app.LoadedApk.forgetReceiverDispatcher(LoadedApk.java:1007) at android.app.ContextImpl.unregisterReceiver(ContextImpl.java:1358) at android.content.ContextWrapper.unregisterReceiver(ContextWrapper.java:608) at com.shah.neeraj.s.MainActivity.onPause(MainActivity.java:66) – Jacks Apr 28 '17 at 08:47
  • @Jacks Read http://stackoverflow.com/questions/6165070/receiver-not-registered-exception-error – IntelliJ Amiya Apr 28 '17 at 08:53
  • @Jacks you should add this `onResume()` also – IntelliJ Amiya Apr 28 '17 at 08:53
  • If i am unregistering then i am not getting screen on time only getting screen off time – Jacks Apr 28 '17 at 09:27
  • in onCreate() if i am register and unregistered then not getting screen on time getting only screen off time. while if doing only registering then getting screen on /off time but when closing the app getting crash witherror " Are you missing a call to unregisterReceiver()?" – Jacks Apr 28 '17 at 10:09
  • After registering and unregistered when i press home button and swipe to stop app app crashed – Jacks Apr 28 '17 at 12:51
0

You are registering receiver but not unregistering it.

Your should register and unregister Receiver in onResume() and onPause() (or onStart() and onStop()) respectively.

Sangeeta
  • 961
  • 2
  • 13
  • 34
-1

Uncomment this ,

BroadcastReceiver mReceiver = new ScreeReceiver();
    unregisterReceiver(mReceive);

The error is suggesting that you are not unregistering the receiver.

Dishonered
  • 8,449
  • 9
  • 37
  • 50