Recently we started development for an app at Truiton , in which we had to maintain sessions locally, the situation was, that if we minimize the app by tapping home key or any other key, the app’s session should log out automatically after 10 minutes. Hence I had to figure out a way in Android to Force Close Application : Session Timeout.
Now the question arises how do I close my app/session programmatically ?
The task at hand is, we do not have to force close application: session timeout immediately as user minimizes the app. Hence the first approach that came into my mind was to schedule a task to force close application:session timeout in Android. We did this by AlarmManager class of android. With the help of AlarmManager we called a BroadcastReceiver which sent the final broadcast via sendBroadcast method.
Here it goes, we’ll start by creating the layout for our main activity.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:background="#FFFFFF" > <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button1" android:layout_centerHorizontal="true" android:layout_marginTop="40dp" android:text="Session Timed Out - Please relogin" android:visibility="invisible" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView2" android:layout_alignParentTop="true" android:layout_marginTop="44dp" android:src="@drawable/truiton" /> <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="Login" /> </RelativeLayout>
After creating this layout out screen should look something like this:
Code for MainActivity:
package com.truiton.closebroadcast; import com.truiton.closebroadcast.R; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button b1 = (Button) findViewById(R.id.button1); final Intent i = new Intent(this, SecondActivity.class); b1.setOnClickListener(new OnClickListener() { public void onClick(View v) { startActivityForResult(i, 1); } }); } @Override protected void onResume() { super.onResume(); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1) { if (resultCode == RESULT_OK) { int result = data.getIntExtra("result", 0); if (result == 1) { TextView TV1 = (TextView) findViewById(R.id.textView2); TV1.setVisibility(TextView.VISIBLE); } } if (resultCode == RESULT_CANCELED) { // code here for cancelled result } } } }
Here we have simply created an activity which listens to an OnClick event of a button via OnClickListener and starts the SecondActivity. Also this MainActivity receives the result and shows the message accordingly when app is force closed/session timeout.
Code for SecondActivity:
package com.truiton.closebroadcast; import java.util.Calendar; import com.truiton.closebroadcast.R; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; public class SecondActivity extends Activity { BroadcastReceiver myReceiver; AlarmManager alarmManager; PendingIntent pendingIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_second); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("truiton.ACTION_FINISH"); myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.v("Second Activity", "Finishing Activity"); /**** Returning Result *****/ Intent returnIntent = new Intent(); returnIntent.putExtra("result", 1); SecondActivity.this.setResult(RESULT_OK, returnIntent); /*********/ /**** Cancel Result ****/ /* * Intent returnIntent = new Intent(); * SecondActivity.this.setResult(RESULT_CANCELED, returnIntent); */ /*********/ finish(); } }; registerReceiver(myReceiver, intentFilter); } @Override protected void onPause() { super.onPause(); Intent myIntent = new Intent(getBaseContext(), MyScheduledReceiver.class); Bundle bundle = new Bundle(); bundle.putInt("val", 8); myIntent.putExtras(bundle); pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, myIntent, 0); alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); calendar.add(Calendar.SECOND, 10); alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); Log.v("Second Activity", "Alarm Scheduled"); } @Override protected void onResume() { super.onResume(); if (alarmManager != null) { alarmManager.cancel(pendingIntent); Log.v("Second Activity", "Scheduled Alarm Cancelled"); } } @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(myReceiver); } }
This SecondActivity is the activity where magic happens. This activity has an onReceive method which is used to receive the broadcast which will be sent from the next class i.e MyScheduledReceiver. This helps in force close application:session timeout on Android. Please define this method in all of the activities which you want to close when session expires (Highlighted Lines) this is the method which finish() is called to end the activity. Have a look at the onPause method if this class, here we are scheduling an alarm of 10 seconds with the help of AlarmManager, Intent, PendingIntent and Calendar classes.
Code for MyScheduledReceiver :
package com.truiton.closebroadcast; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; public class MyScheduledReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent recievedIntent) { // TODO Auto-generated method stub Toast.makeText(context, "Session Timeout", Toast.LENGTH_LONG).show(); Log.v("MyScheduledReceiver", "Intent Fired"); Intent broadcastIntent = new Intent(); broadcastIntent.setAction("truiton.ACTION_FINISH"); context.sendBroadcast(broadcastIntent); } }
In Android to force close application:session timeout, MyScheduledReceiver class is used. Although code for this class is self explanatory, here we are sending a broadcast via sendBroadcast method in onReceive method of receiver. The broadcast intent fired here has an action truiton.ACTION_FINISH which is used to finish the SecondActivity.
This is BroadcastReceiver class therefore we also need to register it as a receiver in manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.truiton.closebroadcast" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.truiton.closebroadcast.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> <activity android:name="com.truiton.closebroadcast.SecondActivity" android:label="@string/app_name" > </activity> <receiver android:name="MyScheduledReceiver" /> </application> </manifest>
Now you should have something like this
To sum up – In this Android Force Close Application-Session Timeout Tutorial we used an AlarmManager to schedule a task, which fires an intent to close (finish) all the open classes and return a result to the main calling class. Although it did not solve my purpose, which was to securely end the session after a specific time, as in this approach if user changes the time after minimizing the app, it does not work as supposed to. I posted this code to help someone who’s working in similar sort of app, as this code can be utilized in numerous ways. If you like this post please like our facebook page for similar updates.
Born in New Delhi, India. A software engineer by profession, an android enthusiast and an evangelist. My motive here is to create a group of skilled developers, who can develop something new and good. Reason being programming is my passion, and also it feels good to make a device do something you want. In a very short span of time professionally I have worked with many tech firms. As of now too, I am employed as a senior engineer in a leading tech company. In total I may have worked on more than 20 projects professionally, and whenever I get spare time I share my thoughts here at Truiton.
Thanks, its a good one.
How can we run same broadcast through out the application
Thanks for this article, I found it really helpful implementing session timeout in an android app I’m currently building.