May 01, 2019

How to save an Android Activity state using save instance state

      On this blog am going to explain how to save activity state when the activity is destroyed, I have been working on the android SDK platform, and it is a little unclear how to save an application's state.


You're explicitly destroying your activity such as by pressing back. Actually, the scenario in which this savedInstanceState is used, is when Android destroys your activity for recreation. For example, If you change the language of your phone while the activity was running (and so different resources from your project need to be loaded). Another very common scenario is when you rotate your phone to the side so that the activity is recreated and displayed in landscape. You can use this technique to store instance values for your application (selections, unsaved text, etc.).


To overcome this issue you need to override onSaveInstanceState(Bundle savedInstanceState) and write the application state values you want to change to the Bundle parameter, This bundle will be passed to onCreate if the process is killed and restarted.


@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  savedInstanceState.putBoolean("KeyBoolean", true);
  savedInstanceState.putDouble("KeyDouble", 1.9);
  savedInstanceState.putInt("KeyInt", 1);
  savedInstanceState.putString("KeyString", "Welcome back to Android");
}


The Bundle is essentially a way of storing the values as  Name-Value Pair, and it will get passed in to onCreate() and also  onRestoreInstanceState(Bundle savedInstanceState) where you would then extract the values like this,


@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  boolean myBoolean = savedInstanceState.getBoolean("KeyBoolean");
  double myDouble = savedInstanceState.getDouble("KeyDouble");
  int myInt = savedInstanceState.getInt("KeyInt");
  String myString = savedInstanceState.getString("KeyString");
}





April 29, 2019

Location Permission checking in Android

                        On this Blog I am going to explain about how to integrate Location Permission checking on your android application. Here is the steps,



Step 1 

        First we need to add the permission for Location Access. For this we need to add the following permissions on our applications AndroidManifest.xml file Here is the permissions we need to add, 

<uses-permission android:name="android.permission.INTERNET" />
<permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Step 2

New we are going to make a function checkLocationPermission() to check the location permission, This  function will return a Boolean value based on the location permission. If the user granted the permission it will return true otherwise it will return false and also it will request for the permission. Here is the function,

LOCATION_REQUEST_CODE
is one constant variable, On your application you can define your own value, I defiled this variable on my Constants.java Class file.

public static final int LOCATION_REQUEST_CODE = 4505;



private boolean checkLocationPermission() {
        boolean permission = false;
        try {
            if (ActivityCompat.checkSelfPermission(HomeActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                permission = true;
            } else
                ActivityCompat.requestPermissions(HomeActivity.this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}, Constants.LOCATION_REQUEST_CODE);
        } catch (Exception e) {
        }
        return permission;
    }

Step 3

Now we need to check the permission on the  onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)  function. Which is a default function in Activity class.  Here is the Method,

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
    case Constants.LOCATION_REQUEST_CODE:
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // permission granted, Add your code after giving permission
       }else{
            //show some warning, or Add your code permission not granded
       }
        break;
     }









---------------
Thanks For Reading, Wish you a Happy Coding....





April 14, 2019

Android Location Tracking In Using Service

             
                                  On this Blog I am going to explain about location update when the applications is running on background. In some cases we need to send location updated to our server when the application is on background. For this I am using startForeground() function.  

     Here LocationService.java is my Service Class which I used to get the location update on Background.


LocationService.java

public class LocationService extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;

    private static final String TAG = "LocationService";
    private static final int LOCATION_INTERVAL = 10000;
    private static final int FASTEST_INTERVAL = 10000;
    @Override
    public void onCreate() {

        if (isGooglePlayServicesAvailable()) {
            mLocationRequest = new LocationRequest();
            mLocationRequest.setInterval(LOCATION_INTERVAL);
            mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            //mLocationRequest.setSmallestDisplacement(10.0f);  /* min dist for location change, here it is 10 meter */
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();

            mGoogleApiClient.connect();
        }
    }

    //Check Google play is available or not
    private boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
        return ConnectionResult.SUCCESS == status;
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "Connected");
        startLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d(TAG, "Connection suspended");
    }

    protected void startLocationUpdates() {
        Log.d(TAG, "Start Location Updates");
        try {
            int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            }
        } catch (IllegalStateException e) {
        }
    }


    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            Log.d(TAG, "Location Changed: " + location.getLatitude() + "," + location.getLongitude());
            //Send Broadcast
            Intent intent = new Intent(getPackageName());
            intent.putExtra(Constants.LocationUpdated, location);
            sendBroadcast(intent);
        }

    }


   /* LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.GPS_PROVIDER),
            new LocationListener(LocationManager.NETWORK_PROVIDER)
    };*/


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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Notification.Builder builder = new Notification.Builder(this, Constants.LOCATION_CHANNEL_ID)
                    .setContentTitle(getString(R.string.app_name))
                    .setContentText(Constants.LocationChange)
                    .setAutoCancel(true);

            Notification notification = builder.build();
            startForeground(1, notification);
        } else {
             NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                    .setContentTitle(getString(R.string.app_name))
                    .setContentText(Constants.LocationChange)
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                    .setAutoCancel(true);
            Notification notification = builder.build();
            startForeground(1, notification);
        }
        return START_NOT_STICKY;
    }


    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.d(TAG, "onConnectionFailed:: " + connectionResult.getErrorMessage());
    }
}


Once you create the Service Class you need to add this service class to AndroidManifest.xml file, Also You need to add the Location permissions if you didn't added on your Manifest file, Here is my Manifest file,

AndroidManifest.xml 


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

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <application
        android:name=".AppController"
        android:allowBackup="true"
        android:hardwareAccelerated="false"
        android:icon="@drawable/logo_squre"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:launchMode="singleInstance"
        android:roundIcon="@drawable/logo_circle"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".HomeActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".service.LocationService" />
    </application>

</manifest>


On the next step you need to create the Notification channel on your application class. We are using createNotificationChannel()method to Create Notification channel, Here us my Application class,


AppController.java


public class AppController extends Application {

    public static final String TAG = AppController.class.getSimpleName();

    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        createNotificationChannel();
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(this);
    }

    public static synchronized AppController getInstance() {
        return mInstance;
    }


    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                    Constants.LOCATION_CHANNEL_ID,
                    getString(R.string.app_name),
                    NotificationManager.IMPORTANCE_DEFAULT
            );

            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(serviceChannel);
        }
    }

}


Next step is to integrate the service class on our Activity class. To handle the broadcast we need to register the Broadcast Receiver on the Activity class. Here I am going to use createBroadcastReceiver() method for Register the Broadcast Receiver.  This method will Invoke in  onCreate(Bundle savedInstanceState) method like,  Here is my method for register the receiver,


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

            //To Register the Receiver 
            broadcastReceiver = createBroadcastReceiver();
            registerReceiver(broadcastReceiver, new IntentFilter(getPackageName()));
    }


    //Method for Register Broadcast receiver 
    private BroadcastReceiver createBroadcastReceiver() {
        return new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent != null) {
                    if (intent.hasExtra(Constants.LocationUpdated)){
                        Location location = AppController.getInstance().getCurrentLocation();
                        if (location != null) {
                            Log.e("Broadcast: ", "New Location: " + location.getLatitude() + "," + location.getLongitude());
                          
                        }
                    }
                }
            }
        };

    }


To start and stop the location location service am using startLocationService()  and stopLocationService() method.

    //Service Intent Decleration 
    Intent locationServiceIntent;


    //Start Location Service
    public void startLocationService() {
        if (locationServiceIntent == null)
            locationServiceIntent = new Intent(this, LocationService.class);
        if (!Helper.isServiceRunning(HomeActivity.this, LocationService.class)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                startForegroundService(locationServiceIntent);
            } else {
                startService(locationServiceIntent);
            }
        }
    }


    //Stop Location service
    public void stopLocationService() {
        if (locationServiceIntent != null && Helper.isServiceRunning(HomeActivity.this, LocationService.class))
            stopService(locationServiceIntent);
    }






---------------
Thanks For Reading, Wish you a Happy Coding....


















April 04, 2019

How to get Notification on Back Stack Change On android

            On this blog I am going to explain How to we can get notification on the fragment change on our Activity Class. In Some Cases we need to get the notification when the fragment is changed. We are using OnBackStackChangedListener for this. Here is the way we are doing it,


First we need to add the Listener on onCreate method of Activity Class . For this I have Created a function addPopBackStackListener(). Here is the way we initializing the  Listener

         @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        
        addPopBackStackListener();


   }

Here is my addPopBackStackListener() function,

   private void addPopBackStackListener() {
        getSupportFragmentManager().addOnBackStackChangedListener(
            new FragmentManager.OnBackStackChangedListener() {
                public void onBackStackChanged() {
                    FragmentManager fragmentManager = getSupportFragmentManager();
                    if (fragmentManager != null && fragmentManager.getFragments() != null) {                   
                    int count = fragmentManager.getFragments().size();
                        if (count > 0) {
                            Fragment fragment = fragmentManager.getFragments().get(count- 1);
                               
                            Log.v(TAG, "Class: " + fragment.getClass().getSimpleName());

                            /* Using instanceof keyword you can find out which fragment is loaded*/
                            if (fragment instanceof HomeFragment) {
                                 /*Add your code to Perform Action when Home Fragment is Loaded*/  

                            } 
                           
                        }
                    }                 
                }
            });
    }



---------------
Thanks For Reading, Wish you a Happy Coding....