Friday, May 31, 2013

Android: Solution to detect when an Android app goes to the background and come back to the foreground without getRunningTasks or getRunningAppProcesses



In Android, we don’t have options directly to find whether our app goes to background or not like applicationdidenterbackground in iOS.
I have gone through lot of articles and forums; everywhere I am finding only one result.

private boolean isApplicationBroughtToBackground() {
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List tasks = am.getRunningTasks(1);
    if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get(0).topActivity;
        if (!topActivity.getPackageName().equals(context.getPackageName())) {
            return true;
        }
    }

    return false;
}

But we can’t use getRunningTasks because android specifies “method is only intended for debugging and presenting task management user interfaces“.

Solution to detect when an Android app goes to the background and come back to the foreground without getRunningTasks or getRunningAppProcesses by using onWindowFocusChanged and onStop method

The solution i tired for my application as shown below.

BaseActivity is a superclass of all the activities.

BaseActivity.java

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.widget.Toast;

/**
 * @author Harsha
 *
 *         BaseActivity class extends Activity
 */
public abstract class BaseActivity extends Activity {

protected static final String TAG = BaseActivity.class.getName();

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

public static boolean isAppWentToBg = false;

public static boolean isWindowFocused = false;

public static boolean isMenuOpened = false;

public static boolean isBackPressed = false;

@Override
protected void onStart() {
Log.d(TAG, "onStart isAppWentToBg " + isAppWentToBg);

applicationWillEnterForeground();

super.onStart();
}

private void applicationWillEnterForeground() {
if (isAppWentToBg) {
isAppWentToBg = false;
Toast.makeText(getApplicationContext(), "App is in foreground",
Toast.LENGTH_SHORT).show();
}
}

@Override
protected void onStop() {
super.onStop();

Log.d(TAG, "onStop ");
applicationdidenterbackground();
}

public void applicationdidenterbackground() {
if (!isWindowFocused) {
isAppWentToBg = true;
Toast.makeText(getApplicationContext(),
"App is Going to Background", Toast.LENGTH_SHORT).show();
}
}

@Override
public void onBackPressed() {

if (this instanceof MainActivity) {

} else {
isBackPressed = true;
}

Log.d(TAG,
"onBackPressed " + isBackPressed + ""
+ this.getLocalClassName());
super.onBackPressed();
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {

isWindowFocused = hasFocus;

if (isBackPressed && !hasFocus) {
isBackPressed = false;
isWindowFocused = true;
}

super.onWindowFocusChanged(hasFocus);
}

public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
break;
case R.id.action_settings:
Intent i = new Intent(this, SettingActivity.class);
startActivity(i);
break;
}
return true;
}

@Override
public boolean onMenuItemSelected(int featureId, android.view.MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
break;
case R.id.action_settings:
Intent i = new Intent(this, SettingActivity.class);
startActivity(i);
break;
}
return true;
}

}

Each of the activity classes extendes BaseActivity class to track the application status.

MainActivity.java

import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;

public class MainActivity extends BaseActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

((ImageButton) findViewById(R.id.SecondBtn))
.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(),
SecondActvity.class));
}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}

SecondActvity.java

import android.os.Bundle;

public class SecondActvity extends BaseActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
}

}
 App output looks as :




Improvements
If you want to see an example without having common base class, see app-foreground-n-background-using-callbacks-in-application. It also gives the Solution to detect when an Android app goes to the background and come back to the foreground without getRunningTasks or getRunningAppProcesses. This example supports from API level 14 and above because they interface classes used are added from API level 14.

Source Code
You can download the source code by clicking here: AppStatus-SourceCode.  This project is built using eclipse IDE. Unzip and import the project into Eclipse, it’s a good idea to use the Project by clean and rebuild from the project menu. It works in all API levels.


Thanks for reading :) 
Whether this post is helpful?
If you have any other quick thoughts/hints that you think people will find useful, feel free to leave a comment.  

Thursday, April 25, 2013

Solution: Actionbar Space or Padding between homeasupindicator and app icon

Actionbar support starts from android version 3.0+

If you want to apply style for actionbar then add values-v11 is the values of the API version 11, and values-v14 is the values of the API version 14 in the res folder/ when your minSdkVersion is less than 11.
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" />

Using Themes, getting space between homeAsUpIndicator and App Icon is not working but it is possible through programatically.

android:homeAsUpIndicator : Specifies a drawable to use for the 'home as up' indicator.

programatically:
setDisplayHomeAsUpEnabled(true) shows the "<" on the action bar.

Style:
android:homeAsUpIndicator allows to change the icon

<item name="homeAsUpIndicator">@drawable/custom_home</item>



Solution:
Access the homeAsUpIndicator from the app by calling the android.R.id.home.
Change padding so that we will get space between homeAsUpIndicator and App Icon.
((ImageView) android.R.id.home).setPadding(7,0,7,0)




Wednesday, March 20, 2013

Aptitude: Easy Solution to find Square and Square root of a number


Square of numbers ending with 5
It’s simple logic, any multiplication of 5 will end with 25, so at end of the result it will be 25, in the result starting, it will be the multiplication of n * (n+1)
For Eg: 35 * 35
Where n = 3,
 3 * (3+1) = 3*4 = 12.
Append 25 to the result the answer is 1225
5
15
25
5
15
25
=
=
=
0 * (0+1) 25
1 * (1+1) 25
2 * (2+1) 25
25
225
625

Square of numbers ending with 1, 4, 6 and 9.
There is a small logic for this numbers ending.
For 1 and 6
262 = 252 + (25+26) = 625 + 51 = 676
712 = 702 + (70+71) = 4900 + 141 = 5041
For 4 and 9
242 = 252 – (25+24) = 625 – 49 = 576
692 = 702 - (70+69) = 4900 - 139 = 4761
Square root for four digit number.
First right out the squares from1 to 9.
1             1
2             4
3             9
4             16
5             25
6             36
7             49
8             64
9             81

Number ends with
1                 1 and 9
4                 2 and 8
9                 3 and 7
6                 4 and 6
5                 5

For Ex: find the square root for 1156
Now, Split the number 1156 as 11 and 56
Check where the first split lies between the nearest squares.
9 ≤ 11 ≤ 16
32 ≤ 11 ≤ 42
The lowest nearest one has to be taken here. Means, we are going to take 3.
So, the result of the first number will be 3
Multiple with n+1 number, for ex, the lowest nearest one is 3, then n=3.
So, multiple n with n+1 as below
3 * 4 = 12

Check whether 12 is less than 11 or not.
Since the unit number of 1156 is 6, as per the table the number can be 4 or 6.
If it is less take 4 else 6.
Since 12 is greater than 11, we are going to take 6.

So, the square root of 1156 is 36.

One More Ex:

Let check for 2401
Split number 24 and 01

16 ≤ 24 ≤ 25
42 ≤ 24 ≤ 52

4*5 = 20

Unit digit is 1, so the result of end number can be 1 and 9
24 is the first split one,
Check 20 with 24 is greater than or less than the first split number,
20 < 24
So take 9.

Result = 49

Let check for 1681
Split number 16 and 81

16 ≤ 16 ≤ 25
42  ≤ 16 ≤ 52

4*5 = 20

Unit digit is 1, so the result of end number can be 1 and 9
16 is the first split one,
Check whether 16 with 20, 20 > 16, and so take 1.
Result = 41