Android – Get current location of user by using LocationManager API

Sometimes we need to get user current location from Android device. Its very simple while we use LocationManager API of Android. We just need a custom location manager and a location listener with  necessary permission in Manifest.xml file.  lets see how to do it.

Step-1: Follow the code in manifest.xml file.

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

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

    <uses-feature android:name="android.hardware.location.gps" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme.NoActionBar">
        <activity android:name=".MainActivity" />

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

  
        <activity android:name=".HomeActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
</manifest>

Step-2: Follow these code for TestLocationManager.Java

public class TestLocationManager {

private int minDistanceForUpdateLocation;
private int minTimeForUpdateLocastion;
LocationManager locationManager;
TestLocationListener locationListener;
Context ctx;
private boolean isGPSProviderEnable, isNetworkProviderEnable;

//COnstructor
public TestLocationManager(Context ctx){
this.ctx = ctx;
}

public TestLocationManager(Context ctx, int minTimeForUpdateLocastion, int minDistanceForUpdateLocation ){
this.minDistanceForUpdateLocation =minDistanceForUpdateLocation;
this.minTimeForUpdateLocastion= minTimeForUpdateLocastion;
this.ctx = ctx;
}

//Set Location Manager and Listener
public void setLocationManagerAndListener(){
this.locationListener = new TestSendLocationListener(this.ctx);
this.locationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);

isGPSProviderEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkProviderEnable = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

if(isGPSProviderEnable){
this.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTimeForUpdateLocastion, minDistanceForUpdateLocation, locationListener);
}else if(isNetworkProviderEnable){
this.locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, minTimeForUpdateLocastion, minDistanceForUpdateLocation, locationListener);
}

}

//Get Minimum Distance for updating location
public int getMinDistanceForUpdateLocation() {
return minDistanceForUpdateLocation;
}
//Set Minimum Distance for updating location
public void setMinDistanceForUpdateLocation(int minDistanceForUpdateLocation) {
this.minDistanceForUpdateLocation = minDistanceForUpdateLocation;
}

//Get Minimum Time for updating location
public int getMinTimeForUpdateLocastion() {
return minTimeForUpdateLocastion;
}

//Set Minimum Time for updating location
public void setMinTimeForUpdateLocastion(int minTimeForUpdateLocastion) {
this.minTimeForUpdateLocastion = minTimeForUpdateLocastion;
}
}

Step:3- Follow these code for TestLocationListener.java

public class TestLocationListener implements LocationListener {

private double lat, lng, alt, acc, time;
Context ctx;
ConnectivityDetector connectivityDetector;

public TestLocationListener(Context ctx){
this.ctx = ctx;
}

@Override
public void onLocationChanged(Location location) {
this.lat = location.getLatitude();
this.lng = location.getLongitude();
this.alt = location.getAltitude();
this.acc = location.getAccuracy();
this.time = location.getTime();

Toast.makeText(ctx, “Lat : “+this.lat+” \n Lng : “+this.lng+” \nAlt : “+this.alt+” \n Acc : “+this.acc+” \n Time : “+this.time, Toast.LENGTH_LONG).show();

//to whatever you want with location

}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override
public void onProviderEnabled(String provider) {

}

@Override
public void onProviderDisabled(String provider) {

}
}

Step:4 – There is the code for MainActivity.java . where we will implement our TesetLocationManager and TestLocationListener .

public class MainActivity extends AppCompatActivity{

    private Toolbar toolbar;
    private Location mLastLocation;

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

 // setup toolbar
 toolbar = (Toolbar) findViewById(R.id.toolbar);
 setSupportActionBar(toolbar);


 navigationView = (NavigationView) findViewById(R.id.menu_main);
 navigationView.setNavigationItemSelectedListener(this);
 //Set default item selected on nivigation
 navigationView.getMenu().performIdentifierAction(R.id.menu_home, 0);
 setTitle("");

 //get real time permission for location
 getPermissionForLocation();
 }

 protected void onStart() {
 super.onStart();
 }

 protected void onStop() {
 super.onStop();
 }

 @Override
 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
 super.onRequestPermissionsResult(requestCode, permissions, grantResults);
 switch (requestCode) {
 case ConstantCollection.PERMISSION_REQUEST_LOCATION_COARSE: {
 // If request is cancelled, the result arrays are empty.
 if (grantResults.length > 0
 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
 Toast.makeText(getApplicationContext(), "Permission granted", Toast.LENGTH_LONG).show();

 //setup location manager and listener
 setupLocationManagerAndListener();

 //get last known location
 //mLastLocation = getUserLocation();
 //storeUserLocation(mLastLocation);


 } else {
 MainActivity.this.finish();
 Toast.makeText(getApplicationContext(), "Permission denied! You must have to allow this permission", Toast.LENGTH_LONG).show();
 }
 return;
 }
 }
 }


 //Check Permission and get call log list
 private void getPermissionForLocation() {
 // Here, thisActivity is the current activity
 if (ActivityCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION)
 != PackageManager.PERMISSION_GRANTED
 && ActivityCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.ACCESS_COARSE_LOCATION)
 != PackageManager.PERMISSION_GRANTED) {

 // Should we show an explanation?
 if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
 Manifest.permission.ACCESS_COARSE_LOCATION) ||
 ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
 Manifest.permission.ACCESS_FINE_LOCATION)) {

 // Show an expanation to the user *asynchronously* -- don't block
 // this thread waiting for the user's response! After the user
 // sees the explanation, try again to request the permission.

 ActivityCompat.requestPermissions(MainActivity.this,
 new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
 ConstantCollection.PERMISSION_REQUEST_LOCATION_COARSE);

 } else {
 // No explanation needed, we can request the permission.
 ActivityCompat.requestPermissions(MainActivity.this,
 new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
 ConstantCollection.PERMISSION_REQUEST_LOCATION_COARSE);

 }
 } else {
 //Check permission for location
 setupLocationManagerAndListener();
 
 }
 }

 //setup location location manager and listener
 private void setupLocationManagerAndListener(){
 TestLocationManager locationManager = new TestLocationManager(MainActivity.this, 10000, 10);
 TestLocationListener locationListener = new TestLocationListener(getApplicationContext());
 locationManager.setLocationManagerAndListener();
 }

}

We can find our expected location on onLocationChanged() method of TestLocationListener.java file. So i think you got your expected result. If you have any question then put it on comment box. Thanks.

Android – Network call using volley

Today i am going to show you how to perform network call or http request in android using volley. Volley is a library for network call on Android.

Volley offers the following benefits:

– Automatic scheduling of network requests.
– Multiple concurrent network connections.
– Transparent disk and memory response caching with standard HTTP cache coherence.
– Support for request prioritization.
– Cancellation request API. You can cancel a single request, or you can set blocks or scopes of requests to cancel.
– Ease of customization, for example, for retry and backoff.
– Strong ordering that makes it easy to correctly populate your UI with data fetched asynchronously from the network.
– Debugging and tracing tools.
– All type of HTTP request can be done by volley including image request from a remote server.

Lets see how we can implement a volley request.

Step-1 : We need to put a permission for internet access on our manifest.xml.

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

<uses-permission android:name="android.permission.INTERNET" />

<application

android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".WelcomeActivity"
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>

Step-2 : I found many times that it never sends any extra parameter through the request object. Although it has option but it does not work. So i searched on google and got a class that is extended from Request class of volley. Where we can send extra parameter. So lets make our custom VolleyRequest.java class.

public class VolleyRequest extends Request<JSONObject> {

    private Response.Listener<JSONObject> listener;
    private Map<String, String> params;

    public VolleyRequest(String url, Map<String, String> params,
                         Response.Listener<JSONObject> reponseListener, Response.ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    public VolleyRequest(int method, String url, Map<String, String> params,
                         Response.Listener<JSONObject> reponseListener, Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    @Override
    protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
        return params;
    };

    @Override
    protected void deliverResponse(JSONObject response) {
        listener.onResponse(response);
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

}

Step-3: Our HttpRequestCollection.java class. Where we will write several type of request which we will call as needed.

public class HttpRequestCollection {
    private Context context;
    private JSONObject jsonObject;

    public HttpRequestCollection(Context context){
        this.context = context;
        this.jsonObject = new JSONObject();
    }

    //get request method
    public JSONObject sendGetRequest(String url, Map<String, String> params){
        //clear json object first
        Iterator keys = jsonObject.keys();
        while(keys.hasNext()) {
            jsonObject.remove(keys.next().toString());
        }

        VolleyRequest volleyRequest = new VolleyRequest(Request.Method.GET, url, params, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                jsonObject = response;
                try {
                    jsonObject = jsonObject.put("success_request", true);
                    jsonObject = jsonObject.put("message", "Request successful");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                try {
                    jsonObject= jsonObject.put("success_request", false);
                    jsonObject= jsonObject.put("message", "Request failed");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        Volley.newRequestQueue(context).add(volleyRequest);

        return jsonObject;
    }


    //post request method
    public JSONObject sendPostRequest(String url, Map<String, String> params){

        //clear json object first
        Iterator keys = jsonObject.keys();
        while(keys.hasNext()) {
            jsonObject.remove(keys.next().toString());
        }

        VolleyRequest volleyRequest = new VolleyRequest(Request.Method.POST, url, params, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                jsonObject = response;
                try {
                    jsonObject = jsonObject.put("success_request", true);
                    jsonObject = jsonObject.put("message", "Request successful");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                try {
                    jsonObject= jsonObject.put("success_request", false);
                    jsonObject= jsonObject.put("message", "Request failed");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });

        Volley.newRequestQueue(context).add(volleyRequest);

        return jsonObject;
    }
}

Step-4 : Our MainActivity.java for activity.

 public class MainActivity extends AppCompatActivity {

private String message;
private TextView tvMessage;
private Button btnSubmit;

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

tvMessage = (TextView) findViewById(R.id.tvMessage);
btnSubmit = (Button) findViewById(R.id.btnSubmit);

} //ENd of onCreate

} 

Blocking call and sms in Android programmatically

Today i am going to show you how to block call and sms in Android including latest version (Kitkat, Lollipop, Marshmallow etc). Most of our work will be done in BroadcastReceiver class.

Broadcast Receiver – A broadcast receiver (short receiver ) is an Android component which allows you to register for system or application events. All registered receivers for an event are notified by the Android runtime once this event happens. Read more about BroadcastReceiver.

Follow these steps given below :

Step -1 : At first, we need to prepare our Manifest.xml file with a BroadcastReceiver and necessary permission, like- RECEIVE_SMS, CALL_PHONE, READ_PHONE_STATE. Permission’s are –

<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Permission “android.permission.RECEIVE_SMS” is for allowing an application to receive SMS messages.
And permission “android.permission.READ_PHONE_STATE” is for allowing read only access to phone state, including the phone number of the device, current cellular network information, the status of any ongoing calls, and a list of any PhoneAccounts registered on the device.

And The BraodcastReceiver named PhoneStateReceiver for receiving call and  sms is –

<receiver
android:name="com.test.blocker.PhoneStateReceiver"
android:enabled="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="9999">
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

We registered a broadcast receiver “PnoheStateReceiver” by receiver node. And “intent-filter”  is used to filter the intent action which is being received. We provided two action here. These are –  Action “android.intent.action.PHONE_STATE” is used to  receive all phone state, including the phone number of the device, current cellular network information, the status of any ongoing calls. And action “android.provider.Telephony.SMS_RECEIVED” is used to receive sms messages.

In the priority of intent-filter, the value must be an integer, such as “10>”. Higher numbers have a higher priority of receiver to receive the intent . The default value is 0. The value must be greater than -1000 and less than 1000.

Step -2 : Now its time to implement our PhoneStatereceiver.java class which is our broadcast receiver. Lets see the example .

public class PhoneStateReceiver extends BroadcastReceiver {

private String blockingNumber = "XX-XXX-XXXXX";

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

//blocking sms for matched number

if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
Bundle bundle = intent.getExtras();
 Object messages[] = (Object[]) bundle.get("pdus");
 SmsMessage smsMessage[] = new SmsMessage[messages.length];

 for (int n = 0; n < messages.length; n++) {
 smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
 }

 final String numberSms = smsMessage[0].getOriginatingAddress();
 //final String messageSms = smsMessage[0].getDisplayMessageBody();
 //long dateTimeSms = smsMessage[0].getTimestampMillis();

//block sms if number is matched to our blocking number 
if(numberSms.equals(blockingNumber)){
 abortBroadcast(); 
} 
} 
} 
}

Here “blockingNumber” is the number which will be blocked for call and sms. “onReceive(final Context context, final Intent intent)” method will be called each time when receiver is notified with context and intent data. All information of sms such as number, message body, time etc will be found from intent provided by onReceive method. We got the number/address of sms by calling  getOriginatingAddress() method from extracted pdus information from intent. Also we can get message body and time by calling getDisplayMessageBody() and getTimestampMillis() method from extracted pdus information. These are not related to block number. I just show you how to get message body and time also. It can be needed for further process. If this numberSms is matched with our blockingNumber then broadcast receiver will be aborted. And this is the mechanism for blocking sms.

Step – 3 : Now lets see implementation of PhoneStateReceiver.java and how to block call for matched number. Follow the example

public class PhoneStateReceiver extends BroadcastReceiver {

private String blockingNumber = "XX-XXX-XXXXX";

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

//blocking sms for matched number

if (intent.getAction().equals("android.intent.action.PHONE_STATE")){
 final String numberCall = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);;
 
//reject call if number is matched to our blocking number 
if(numberCall.equals(blockingNumber)){
 disconnectPhoneItelephony(context);
} 
} 
} 

 // Keep this method as it is
 @SuppressWarnings({ "rawtypes", "unchecked" })
 private void disconnectPhoneItelephony(Context context) {
 try {

 String serviceManagerName = "android.os.ServiceManager";
 String serviceManagerNativeName = "android.os.ServiceManagerNative";
 String telephonyName = "com.android.internal.telephony.ITelephony";
 Class<?> telephonyClass;
 Class<?> telephonyStubClass;
 Class<?> serviceManagerClass;
 Class<?> serviceManagerNativeClass;
 Method telephonyEndCall;
 Object telephonyObject;
 Object serviceManagerObject;
 telephonyClass = Class.forName(telephonyName);
 telephonyStubClass = telephonyClass.getClasses()[0];
 serviceManagerClass = Class.forName(serviceManagerName);
 serviceManagerNativeClass = Class.forName(serviceManagerNativeName);
 Method getService = // getDefaults[29];
 serviceManagerClass.getMethod("getService", String.class);
 Method tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder.class);
 Binder tmpBinder = new Binder();
 tmpBinder.attachInterface(null, "fake");
 serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
 IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone");
 Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);
 telephonyObject = serviceMethod.invoke(null, retbinder);
 telephonyEndCall = telephonyClass.getMethod("endCall");
 telephonyEndCall.invoke(telephonyObject);

 } catch (Exception e) {
 e.printStackTrace();
 }
 }
}

For making these code working to latest version android (Kitkat, Lollipop, Marshmallow etc) you need
to make your app as default sms app. To make default sms app -add some features, like sending sms activity and service, mms receiver etc. Because Android changes the rules for receiving sms only. For blocking call
it will working fine.

To make your app as default sms app follow these instructions given below –

Step-1 : At first, add these code on  Manifest.xml file.

<activity android:name="com.test.blocker.MessageActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>

These code will simply add a activity on Manifest.xml file which has some action and data intent filter. These allows your app to receive intents from other apps that want to deliver a message by this activity.

Now create an activity with name MessageActivity.java which will be used for delivering sms.

public class MessageActivity extends AppCompatActivity {

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

        //code for sending sms and use ui 
    }
}

Step-2: Add another broadcast receiver for listening mms on Manifest.xml.

 <!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver
android:name="com.test.blocker.MmsReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />

<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>

And create a broadcast receiver for this with file name MmsReceiver.java.

public class MmsReceiver extends BroadcastReceiver {
public MmsReceiver() {
}

@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
throw new UnsupportedOperationException("Not yet implemented");
}
}

Step-3 : Add a service with name SmsSendService on Manifest.xml file which will deliver sms.

<!-- Service that delivers messages from the phone "quick response" -->
<service
android:name="com.test.blocker.SmsSendService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />

<category android:name="android.intent.category.DEFAULT" />

<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>

And create a service with file name SmsSendService.java.

public class SmsSendService extends Service {
    public SmsSendService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

Step-4: For making default sms app you need to add this code on your launcher activity or any other place.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {                if(!Telephony.Sms.getDefaultSmsPackage(getApplicationContext()).equals(getApplicationContext().getPackageName())) {
                    //Store default sms package name
                    Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
                    intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
                            getApplicationContext().getPackageName());
                    startActivity(intent);
                }
            }

It will show dialog to make your app default sms app and then press ok do it.

Full source code 

1) Manifest.xml file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.blocker.blacklist">
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar">
<activity android:name="com.test.blocker.MessageActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<receiver
android:name="com.test.blocker.PhoneStateReceiver"
android:enabled="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="9999">
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>

<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver
android:name="com.test.blocker.MmsReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />

<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>

<!-- Service that delivers messages from the phone "quick response" -->
<service
android:name="com.test.blocker.SmsSendService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />

<category android:name="android.intent.category.DEFAULT" />

<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>

</manifest>

2) MessageActivity.java

 public class MessageActivity extends AppCompatActivity {

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

       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {                
              if(!Telephony.Sms.getDefaultSmsPackage(getApplicationContext()).equals(getApplicationContext().getPackageName())) {
                    //Store default sms package name
                    Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
                    intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
                            getApplicationContext().getPackageName());
                    startActivity(intent);
                }
            }
//code for sending sms and use ui 
}
 }

3)PhoneStateReceiver.java

public class PhoneStateReceiver extends BroadcastReceiver {

private String blockingNumber = "XX-XXX-XXXXX";

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

//blocking sms for matched number

if (intent.getAction().equals("android.intent.action.PHONE_STATE")){
 final String numberCall = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);;
 
//reject call if number is matched to our blocking number 
if(numberCall.equals(blockingNumber)){
 disconnectPhoneItelephony(context);
} 
} 

//blocking sms for matched number

if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
Bundle bundle = intent.getExtras();
 Object messages[] = (Object[]) bundle.get("pdus");
 SmsMessage smsMessage[] = new SmsMessage[messages.length];

 for (int n = 0; n < messages.length; n++) {
 smsMessage[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
 }

 final String numberSms = smsMessage[0].getOriginatingAddress();
 //final String messageSms = smsMessage[0].getDisplayMessageBody();
 //long dateTimeSms = smsMessage[0].getTimestampMillis();

//block sms if number is matched to our blocking number 
if(numberSms.equals(blockingNumber)){
 abortBroadcast(); 
} 
} 
} 
}
} 

// Keep this method as it is @SuppressWarnings({ "rawtypes", "unchecked" }) 
private void disconnectPhoneItelephony(Context context) { 
try { 
String serviceManagerName = "android.os.ServiceManager";
 String serviceManagerNativeName = "android.os.ServiceManagerNative"; 
String telephonyName = "com.android.internal.telephony.ITelephony"; 
Class<?> telephonyClass; 
Class<?> telephonyStubClass; 
Class<?> serviceManagerClass; 
Class<?> serviceManagerNativeClass; 
Method telephonyEndCall; 
Object telephonyObject; 
Object serviceManagerObject; 
telephonyClass = Class.forName(telephonyName); 
telephonyStubClass = telephonyClass.getClasses()[0]; 
serviceManagerClass = Class.forName(serviceManagerName);
 serviceManagerNativeClass = Class.forName(serviceManagerNativeName); 
Method getService = // getDefaults[29]; 
serviceManagerClass.getMethod("getService", String.class); 
Method tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder.class); 
Binder tmpBinder = new Binder(); tmpBinder.attachInterface(null, "fake"); 
serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder); 
IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone"); 
Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class); 
telephonyObject = serviceMethod.invoke(null, retbinder); 
telephonyEndCall = telephonyClass.getMethod("endCall"); 
telephonyEndCall.invoke(telephonyObject); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
}

I used this same mechanism to develop a call and sms blocking app namely “Blacklist++“. You can check it.

Free versionhttps://play.google.com/store/apps/details?id=com.previewtechs.blacklist
Pro versionhttps://play.google.com/store/apps/details?id=com.previewtechs.blacklistpro

Thanks for reading the article. If you face any problem. Just write on comment box.

Using Google Cloud Messaging (GCM) for push notification on Android Application

Hello everyone today i am going to show how to use Google Cloud Messaging (GCM) in Android application.

GCM sends notification with data from your server to your users’ devices, and receive messages from devices on the same connection. The GCM service handles all aspects of queuing of messages and delivery to client applications running on target devices, and it is completely free.

Step-1: Login on Google Developer Console and create a project . Then export

create_project

And download google-service.json file and put this json file on app directory.

downlaod-google-service-json-file

 

Step-2: Prepare Manifest.xml file

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

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<permission
android:name="com.test.gcmtestapp.permission.C2D_MESSAGE"
android:protectionLevel="signature" />

<uses-permission android:name="com.test.gcmtestapp.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.VIBRATE" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".WelcomeActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<receiver
android:name=".GCMReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>

<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />

<category android:name="com.example.smartsend.smartsendapp" />
</intent-filter>
</receiver>

<service android:name=".GCMMessageHandler" />

</application>

</manifest>

Step-3: Register you device and get token. Create an activity ReagisterActivity.java and place the code on onCreate() method.

//Background Task for registering

 new AsyncTask() {
GoogleCloudMessaging gcm = null;
projectNumber = your project number from google developer console ;

@Override
protected void onPreExecute() {
super.onPreExecute();
}

@Override
protected Object doInBackground(Object[] params) {

try {
if(gcm == null){
gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
}

if(gcm != null){
deviceRegIdForGCM = gcm.register(projectNumber);
}

if(deviceRegIdForGCM != null){
//store  the deviceRegIdForGCM to server 
}else{

}

} catch (Exception e) {
e.printStackTrace();
}

return null;
}

@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);

}
}.execute(null,null,null);
//End of registering rider device

The register() method of GoogleCloudMessaging class requires project number of your project from google developer console and it will return device registration id which is unique and its required to send notification to android device. You must need to store this id to server. This ID is the only identification number of your device for gcm.

 

Step-4: Create  a class GCMReceiver.java that extends WakefulBroadcastReceiver

public class GCMReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ComponentName cmp = new ComponentName(context.getPackageName(), GCMMessageHandler.class.getName());
startWakefulService(context, (intent.setComponent(cmp)));
setResultCode(Activity.RESULT_OK);
}
}

The message/data which is sent from server can be found from intent on onReceiver() method. This intent is sent to the GCMMessageHandler class for further process.

 

Step-5: Create GCMMessageHandler.java class that extends IntentService 

 public class GCMMessageHandler extends IntentService {

//public static final int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager, cNotificationManager;
NotificationCompat.Builder builder;
public GCMMessageHandler() {
super("GCMMessageHandler");
}

@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
String actionIntent = intent.getAction();

//Check if action is receive or not
if(actionIntent == "com.google.android.c2dm.intent.RECEIVE"){

String successMessage = extras.getString("message");

mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);

PendingIntent contentIntent;
Intent nIntent = new Intent(this, NotificationDetailsActivity.class);
// nIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
nIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

//Bind intent data
nIntent.putExtra("success_message", successMessage);

contentIntent = PendingIntent.getActivity(this, uniqueNotificationId, nIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder mBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(
this).setSmallIcon(R.drawable.icon_notification)
.setContentTitle("SmartSend Notification")
.setStyle(new NotificationCompat.BigTextStyle().bigText("New message"))
.setContentText("New message").setWhen(System.currentTimeMillis());

//Set large Icon
Bitmap largeIcon = BitmapFactory.decodeResource(getResources(), R.drawable.icon_notification_white);
mBuilder.setLargeIcon(largeIcon);

mBuilder.setContentIntent(contentIntent);
mBuilder.setAutoCancel(true);
mNotificationManager.notify(uniqueNotificationId, mBuilder.build());

}

}

}

Data can be found from intent of onHandleIntent() method. The string data we got by key “message” is the data sent from server with same key. After receiving data on receiver it will build a notification with PendingIntent for NotificationDetailsActivity.java with the message sent from server.

Step-6: Create a activity NotificationDetailsActivity.java to go this activity when clicked on notification.

 public class NotificationDetailsActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//Get data from intent
Bundle iData = getIntent().getExtras();

String mesasge= iData.getString("success_message");

//Show message
Toast.makeText(getApplicationContext(), "Message from server :  " + mesasge, Toast.LENGTH_LONG).show();

}

}

Step-7:  Server side script for sending notification to device. I have written the script in PHP.

 <?php

//Send notification
public function send_notification($registatoin_ids, $message){
// Set POST variables
$apiKey = your api key for the project from google developer console;
$url = 'https://android.googleapis.com/gcm/send';
$fields = array(
'registration_ids' => $registatoin_ids,
'data' => $message
);
$headers = array(
'Authorization: key=' . $apiKey,
'Content-Type: application/json'
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
// Execute post
$result = curl_exec($ch);
if ($result === FALSE) {
return false;
}

// Close connection
curl_close($ch);
return $result;

}
$data["success_message"] = "Notification sent successfully";
$data['gcm_reg_id'] = your gcm registration id of the device from database;

$data['MessageFromGCM'] = $this->send_notification_to_rider( array($data['gcm_reg_id']), $data );

if($data['MessageFromGCM']){

echo 'Notification sent successfully';

}else{

echo 'Failed to sent notification';

}

?>

Thats it. If you face any problem to implement it just ask question on comment box. Thanks for reading my article.

Equal serialization and base64 encoding of Java and PHP

Java programming

Sometimes we need to manipulate data from PHP based web server to our Java application by HTTP request. When you need to pass the serialized array or map from Java application to PHP API, you cant use serialization and Base64 encoding process of Java. These processes provide different value than PHP. PHP serialization provides a storable representation of a value, that means a String type data. But Java serialization provides byte type data. Base64 encoding in PHP is to make String of equivalent binary data. These are completely different.  So, you have to do it manually by following some mechanism. Any java developer can understand it. The PhpSerializer.java class is for serializing data like PHP serialization. Lets see the code sample –

 

public class PhpSerializer {

    public String serialize(Integer javaInt) {
        if (javaInt == null) {
            return "N;";
        }
        return "i:" + javaInt.toString() + ";";
    }

    public String serialize(Double javaDouble) {
        if (javaDouble == null) {
            return "N;";
        }
        return "d:" + javaDouble.toString() + ";";
    }

    public String serialize(Boolean javaBoolean) {
        if (javaBoolean == null) {
            return "N;";
        }
        return "b:" + (javaBoolean.equals(Boolean.TRUE) ? 1 : 0) + ";";
    }

    public String serialize(String javaString) {
        if ( javaString == null) {
            return "N;";
        }
        return "s:" + javaString.length() + ":\"" + javaString + "\";";
    }

    public String serialize(List<Object> aList) {
        if (aList == null) {
            return "N;";
        }

        StringBuffer buf = new StringBuffer();
        buf.append("a:").append(aList.size()).append(":{");
        int offset = 0;
        for (Iterator<Object> it = aList.iterator(); it.hasNext();) {
            buf.append(serialize(new Integer(offset ++)));
            Object value = it.next();
            buf.append(serialize(value));
        }
        buf.append("};");
        return buf.toString();
    }

    public void serialize(List<Object> aList,StringBuffer buf) {
        if (aList == null) {
            buf.append("N;");
        }else{
            buf.append("a:").append(aList.size()).append(":{");
            int offset = 0;
            for (Iterator<Object> it = aList.iterator(); it.hasNext();) {
                buf.append(serialize(new Integer(offset ++)));
                Object value = it.next();
                buf.append(serialize(value));
            }
            buf.append("};");
        }
    }

    public String serialize(Map<Object,Object> aMap) {
        if (aMap == null) {
            return "N;";
        }

        StringBuffer buf = new StringBuffer();
        buf.append("a:").append(aMap.size()).append(":{");
        for (Iterator<Object> it = aMap.keySet().iterator(); it.hasNext();) {
            Object key = it.next();
            buf.append(serialize(key));
            Object value = aMap.get(key);
            buf.append(serialize(value));
        }
        buf.append("}");
        return buf.toString();
    }

    public void serialize(Map<Object,Object> aMap, StringBuffer buf) {
        if (aMap == null) {
            buf.append("N;");
        }else{
            buf.append("a:").append(aMap.size()).append(":{");
            for (Iterator<Object> it = aMap.keySet().iterator(); it.hasNext();) {
                Object key = it.next();
                buf.append(serialize(key));
                Object value = aMap.get(key);
                buf.append(serialize(value));
            }
            buf.append("};");
        }
    }

    public void serialize(final Object[] array, StringBuffer buf)
    {
        int max;
        buf.append("a:");
        max = array.length;
        buf.append(max);
        buf.append(":{");

        for (int i = 0; i < max; i++)
        {
            serialize(Integer.valueOf(i), buf);
            serialize(array[i], buf);
        }
        buf.append('}');
    }

    public void serialize(Integer javaInt, StringBuffer buffer) {
        if (javaInt == null) {
            buffer.append("N;");
        }else {
            buffer.append("i:" + javaInt.toString() + ";");
        }
    }


    public String serialize(Object value) {
        if (value == null) {
            return "N;";
        }
        if (value instanceof Integer) {
            return serialize((Integer) value);
        }

        if (value instanceof Double) {
            return serialize((Double) value);
        }

        if (value instanceof Boolean) {
            return serialize((Boolean) value);
        }

        if (value instanceof List<?>) {
            List<Object> data = (List<Object>) value;
            return serialize(data);
        }

        if (value instanceof Map<?,?>) {
            Map<Object, Object> data = ( Map<Object, Object>) value;
            return serialize(data);
        }

        return serialize((String) value);

    }

    public void serialize(Object value, StringBuffer buffer) {
        if (value == null) {
            buffer.append("N;");
        }
        if (value instanceof Integer) {
            Integer data = (Integer) value;
            serialize(data, buffer);
        }

        if (value instanceof Double) {
            Double data = (Double) value;
            serialize(data, buffer);
        }

        if (value instanceof Boolean) {
            Boolean data = (Boolean) value;
            serialize(data, buffer);
        }

        if (value instanceof List<?>) {
            List<Object> data = (List<Object>) value;
            serialize(data, buffer);
        }

        if (value instanceof Map<?,?>) {
            Map<Object, Object> data = ( Map<Object, Object>) value;
            serialize(data, buffer);
        }

        if(value instanceof String){
            String data = (String) value;
            serialize(data, buffer);
        }

    }
}

 

Another class Base64Encoder.java is for base64 encoding of output of serialization.

 

public class Base64Encoder {

    private static final char[] map1 = new char[64];
    static {
        int i = 0;
        for (char c = 'A'; c <= 'Z'; c++)
            map1[i++] = c;
        for (char c = 'a'; c <= 'z'; c++)
            map1[i++] = c;
        for (char c = '0'; c <= '9'; c++)
            map1[i++] = c;
        map1[i++] = '+';
        map1[i++] = '/';
    }

    private static final byte[] map2 = new byte[128];
    static {
        for (int i = 0; i < map2.length; i++)
            map2[i] = -1;
        for (int i = 0; i < 64; i++)
            map2[map1[i]] = (byte) i;
    }


    public static String encodeString(String s) {
        byte[] in = s.getBytes();
        int iOff = 0;
        int iLen = in.length;

        int oDataLen = (iLen * 4 + 2) / 3;
        int oLen = ((iLen + 2) / 3) * 4;
        char[] out = new char[oLen];
        int ip = iOff;
        int iEnd = iOff + iLen;
        int op = 0;
        while (ip < iEnd) {
            int i0 = in[ip++] & 0xff;
            int i1 = ip < iEnd ? in[ip++] & 0xff : 0;
            int i2 = ip < iEnd ? in[ip++] & 0xff : 0;
            int o0 = i0 >>> 2;
            int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
            int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
            int o3 = i2 & 0x3F;
            out[op++] = map1[o0];
            out[op++] = map1[o1];
            out[op] = op < oDataLen ? map1[o2] : '=';
            op++;
            out[op] = op < oDataLen ? map1[o3] : '=';
            op++;
        }
        return new String(out);
    }
}

Now lets see an example that how we can implement it.

public class Test {
    public static void main(String[] args) {
        Map<Integer, String> languages = new HashMap<Integer, String>();
        languages.put(0, "Java");
        languages.put(1, "PHP");
        languages.put(2, "Objective-C");
        languages.put(3, "Swift");
        languages.put(4, "Ruby");

        PhpSerializer phpSerializer = new PhpSerializer();
        String serializedMap = phpSerializer.serialize(languages);
        String base64MapString = Base64Encoder.encodeString(serializedMap);

        System.out.println("Serialized map in Java : "+ serializedMap);
        System.out.println("Base64 map string in Java : "+ base64MapString);
    }
}

The output is –

 Serialized map in Java : a:5:{i:0;s:4:"Java";i:1;s:3:"PHP";i:2;s:11:"Objective-C";i:3;s:5:"Swift";i:4;s:4:"Ruby";}

Base64 map string in Java : YTo1OntpOjA7czo0OiJKYXZhIjtpOjE7czozOiJQSFAiO2k6MjtzOjExOiJPYmplY3RpdmUtQyI7aTozO3M6NToiU3dpZnQiO2k6NDtzOjQ6IlJ1YnkiO30=

Now lets try to make it on PHP –

<?php 
 $languages = [
 0 => "Java",
 1 => "PHP",
 2 => "Objective-C",
 3 => "Swift",
 4 => "Ruby"
 ];

 $serializedArray = serialize($languages);
 $base64Encoded = base64_encode($serializedArray);
 
 echo "Serialize array in php : ".$serializedArray;
 echo "<br/> Base64 encoded serialized array in php : ".$base64Encoded;
?>

And the output is –

Serialize array in php : a:5:{i:0;s:4:"Java";i:1;s:3:"PHP";i:2;s:11:"Objective-C";i:3;s:5:"Swift";i:4;s:4:"Ruby";}

Base64 encoded serialized array in php : YTo1OntpOjA7czo0OiJKYXZhIjtpOjE7czozOiJQSFAiO2k6MjtzOjExOiJPYmplY3RpdmUtQyI7aTozO3M6NToiU3dpZnQiO2k6NDtzOjQ6IlJ1YnkiO30=

So, the result is same on both of Java and PHP. I think you got your expected output. Thank you.