How to Monitor Incoming SMS in Android API <19 & API >=19? - android

Am try to Monitoring Incoming SMS in my App. From Android Side they done some change for Monitoring incoming SMS from API 19.
Can't Track incoming Message in Background(at the time of App not in Background & Mobile Screen in Off State) in API 23.
In Android Document said Can't Track Incoming SMS in Background if your app is not as a Default Message App From API 19.
Ref:- Getting Your SMS Apps Ready for KitKat
But its working on My API 21(LOLLIPOP) device. It will not working on API 23(Marshmallow) devices. When Devices Screen is on or the app is open means it Working in API 23(Marshmallow) also.
Can You Please Update Me Is there any Way to Track Incoming Message in Background in API 23(Marshmallow).
Manifest Code
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<receiver
android:name=".SMSReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="5822">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Here My Java Code
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
public class SMSReceiver extends BroadcastReceiver {
public static final String BROADCAST = "SMS_RECEIVER";
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
Intent broadcast_intent;
String message_body = "", originAddress;
StringBuilder bodyText;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equalsIgnoreCase(SMS_RECEIVED)) {
broadcast_intent = new Intent(BROADCAST);
Bundle bundle = intent.getExtras();
SmsMessage[] messages;
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
messages = new SmsMessage[pdus.length];
bodyText = new StringBuilder();
for (int i = 0; i < messages.length; i++) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String format = bundle.getString("format");
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format);
} else {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
originAddress = messages[i].getOriginatingAddress().toUpperCase();
bodyText.append(messages[i].getMessageBody());
}
message_body = bodyText.toString();
}
}
}
}

At the beginning of introducing Android 6.0 (API 23) Google made a huge change in app permission technique.So for API >=23 users needs to grant permissions to apps while the app is running, not when they install the app
System permissions are divided into two categories, normal and dangerous:
Normal permissions do not directly risk the user's privacy. If your app lists a normal permission in its manifest, the system grants the permission automatically.
Dangerous permissions can give the app access to the user's confidential data. If your app lists a normal permission in its manifest, the system grants the permission automatically. If you list a dangerous permission, the user has to explicitly give approval to your app.
Permission for Accessing the phones sms manager is considered as Dangerous Permission and that's why it needs to be called programmatically inside your code where you are trying to use phones smsmanager.
You can request permission in your mainActivity like this
int hasSMSPermission = checkSelfPermission( Manifest.permission.SEND_SMS );
List<String> permissions = new ArrayList<String>();
if( hasSMSPermission != PackageManager.PERMISSION_GRANTED ) {
permissions.add( Manifest.permission.SEND_SMS );
}
if( !permissions.isEmpty() ) {
requestPermissions( permissions.toArray( new String[permissions.size()] ), REQUEST_CODE_SOME_FEATURES_PERMISSIONS );
}
And to receive the request result of permission and set up your brodcast receiver make an override method of onActivityResult like this:
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch ( requestCode ) {
case REQUEST_CODE_SOME_FEATURES_PERMISSIONS: {
for( int i = 0; i < permissions.length; i++ ) {
if( grantResults[i] == PackageManager.PERMISSION_GRANTED ) {
Log.d( "Permissions", "Permission Granted: " + permissions[i] );
} else if( grantResults[i] == PackageManager.PERMISSION_DENIED ) {
Log.d( "Permissions", "Permission Denied: " + permissions[i] );
}
}
}
break;
default: {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
see this link for more details : https://developer.android.com/training/permissions/requesting.html

Basically you can register a broadcast receiver to listen for SMS_Receive and check out the following.
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("mySMS");
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
SmsMessage sms = SmsMessage.createFromPdu((byte[])pdus[0]);
Log.i(TAG, "smsActivity : SMS is <" + sms.getMessageBody() +">");
String message = sms.getMessageBody();
//required sms
TextView tx = (TextView) findViewById(R.id.TextBox);
tx.setText(message);
} else
Log.i(TAG, "smsActivity : NULL SMS bundle");

Related

Broadcast Receiver not working in Oppo,Mi and some other phones when application is closed

I am trying to detect incoming sms, for that I have created Broadcast Receiver to listen to the incoming sms.
It works perfectly when the app is in the Foreground.But when I close the app from the recent apps then on some phones like Oppo and xiaomi the Receiver stopped working and is killed.
Below is the code I have implemented:
SmsReceiver.java
public class SmsReceiver extends BroadcastReceiver {
SmsMessage currentMessage;
public SmsReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, " reciever called ", Toast.LENGTH_SHORT).show();
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");
for (int i = 0; i < pdus.length; i++) {
//SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
currentMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
} else {
currentMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
String sender = currentMessage.getDisplayOriginatingAddress();
if (sender.contains("HP-CRAZND")) {
String messageBody = currentMessage.getMessageBody();
if (messageBody.toString() != null || !messageBody.toString().isEmpty()) {
Intent ii = new Intent(context, MyService.class);
ii.putExtra("s", sender);
ii.putExtra("m", messageBody);
context.startService(ii);
}
}
}
}
}
AndroidManifest.xml:
I have added the receiver as below
<receiver
android:name="saiinfotech.sms.SmsReceiver">
<intent-filter android:priority="100">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
enable app in autostart then its working fine
using kotlin, here two extension function first one get manufacturing detail
second one is to open setting to auto start app
//call this method to get manufacturing detail of mobile
fun Context.checkManufacturing(): Intent? {
var intent:Intent?=null
try {
intent=Intent()
val manufacturer = android.os.Build.MANUFACTURER
if ("xiaomi".equals(manufacturer, ignoreCase = true)) {
intent?.component = ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")
packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
return intent
} else if ("oppo".equals(manufacturer, ignoreCase = true)) {
intent?.component = ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")
packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
return intent
} else if ("vivo".equals(manufacturer, ignoreCase = true)) {
intent?.component = ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")
packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
return intent
}
return null
} catch (e: Exception) {
e.message!!.toast()
return null
}
return null
}
/// pass intent here get fron check manufacturing method to open setting
fun Intent.autostart(context: Context){
context.startActivity(this)
}
Actually I believe that is not related to manufacturer. One needs a service to do it in background, ongoing, survive activity destroy.
If one needs to do it from time to time, use a Jobscheduler with a builder and set Periodic and to persist reboot. setPersisted(true).
By the way, what API in Xiaomi and Oppo?

how to cancel/prevent the propagation of default sms app in marshmallow [duplicate]

I was trying to block all the incoming sms in my android device.
This is the code i was using-
public class SmsReceiver extends BroadcastReceiver {
/**
* Called when the activity is first created.
*/
private static final String ACTION = "android.provider.Telephony.SEND_SMS";
public static int MSG_TPE = 0;
#Override
public void onReceive(Context context, Intent intent) {
String MSG_TYPE = intent.getAction();
if (MSG_TYPE.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]);
}
// show first message
Toast toast = Toast.makeText(context, "BLOCKED Received SMS: " + smsMessage[0].getMessageBody(), Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
for (int i = 0; i < 8; i++) {
Log.i("log", "Blocking SMS **********************");
}
} else if (MSG_TYPE.equals("android.provider.Telephony.SEND_SMS")) {
Toast toast = Toast.makeText(context, "SMS SENT: " + MSG_TYPE, Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
for (int i = 0; i < 8; i++) {
Log.i("log", "Blocking SMS **********************");
}
} else {
Toast toast = Toast.makeText(context, "SIN ELSE: " + MSG_TYPE, Toast.LENGTH_LONG);
toast.show();
abortBroadcast();
for (int i = 0; i < 8; i++) {
Log.i("log", "Blocking SMS **********************");
}
}
}
}
Manifest file-
<service android:name=".MyServiceSentReceived" android:enabled="true"/>
<receiver android:name="SmsReceiver">
<intent-filter android:priority="2147483645">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
It shows me blocking sms but again the sms is received. so this piece of code is not working for me. i was following this SO Question.
The other questions i am looking at are -
Block SMS in android
Android Block Incoming SMS using BroadCastReceiver
Do anyone have any suggestion for this.
You cannot block incoming SMS since API 19 (KitKat), unless your app is the default messaging app, and even then you can only stop them from being saved to the SMS Provider.
The SMS_RECEIVED broadcast can no longer be aborted, so any app listening for it will still get it. Furthermore, the default app receives a different broadcast anyway - SMS_DELIVER - which is not received by any other app, and cannot be intercepted.
If your app is the default SMS app, it is responsible for writing the incoming messages to the SMS Provider, so if you don't want them saved there, just don't write them. However, this will have no effect on the SMS_RECEIVED broadcast, which will still be delivered to any app registered for it, though those apps won't be able to write them to the Provider.
The following blog page discusses the SMS API changes, and includes details on the requirements for an app to act as the default messaging app. Do note, though, that the default app is responsible for many, many things - including MMS, as well - and writing a full-blown messaging client is not a trivial task.
Getting Your SMS Apps Ready for KitKat

Read OTP/SMS in MI device not working (Android)

I have integrated Auto read OTP in my code and it's working fine except in MIUI devices. BroadcastReceiver never wake up in case of MI devices when sms is received. After some efforts I think MI devices runs on its Permission Manager where all Permissions regarding read sms are disabled by default as comes in category of Privacy permissions and it looks like this :
Now I can't figure out any way to Notify user first to accept or decline the Permission. Device simply disable the permissions by default after app is Installed in device.Is there any way to notify user to Accept the Permission's when app Installed ?
Some code:
SMSReciever.class - BroadcastReceiver wakes up when SMS is received.
public class SMSReciever extends BroadcastReceiver {
private static final String OTP_LENGTH = "6";
private String otp = "";
private IMessageCallback callable;
private static final String TAG = SMSReciever.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i = 0; i < msgs.length; i++) {
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
try {
String sender = msgs[i].getOriginatingAddress();
String phoneNumber = msgs[i].getDisplayOriginatingAddress();
Log.d(TAG, "onReceive: phone " + phoneNumber);
String message = msgs[i].getMessageBody();
Log.d(TAG, "onReceive: phone " + message);
otp = GetOtp.extractOTP(message, OTP_LENGTH);
if (null != sender && message.contains("OTP for AppName") && !TextUtils.isEmpty(otp)) {
if (callable != null)
callable.getOtp(otp);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
}
public void setMessageCallable(IMessageCallback callable) {
this.callable = callable;
}
public interface IMessageCallback {
void getOtp(String otp);
}
}
AndridManifest.xml - permissions to receive and read sms
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
MI devices can set permissions as per the App. Can you plz check if the your app has SMS permission enabled.
You need to go to Settings > Apps > {your_app} > permissions and check if the SMS permission is enabled. As Xiaomi phones provide per app permissions.

Unable to receive SMS receive broadcast on Galaxy SIII running 4.1.1

I have this problem only on Samsung Galaxy SIII running Android 4.1.1. There is no problem on Samsung Galaxy Ace and Samsung Galaxy Y. The broadcast SMS received is not firing up, when SMS is received. No other SMS app is installed on the phone.
I am using the following code to receive the SMS broadcast
smsReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Inside onReceive of smsReceiver");
Bundle bundle = intent.getExtras();
Object[] messages = (Object[]) bundle.get("pdus");
SmsMessage[] sms = new SmsMessage[messages.length];
// Create messages for each incoming PDU
for (int n = 0; n < messages.length; n++) {
sms[n] = SmsMessage.createFromPdu((byte[]) messages[n]);
}
for (SmsMessage msg : sms) {
//do something
}
}
};
IntentFilter intentFilter = new IntentFilter();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1);
} else {
// set Interger.MAX_VALUE because other apps like Handcent are intercepting
intentFilter.setPriority(Integer.MAX_VALUE);
}
intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
// register receiver for receive SMS
registerReceiver(smsReceiver, intentFilter);
I have set the following permission in the Manifest
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
I don't have logcat access.
I have spend last two days trying to find the cause in the maze of Android but no help.

How to get the device's IMEI/ESN programmatically in android?

To identify each devices uniquely I would like to use the IMEI (or ESN number for CDMA devices). How to access this programmatically?
You want to call android.telephony.TelephonyManager.getDeviceId().
This will return whatever string uniquely identifies the device (IMEI on GSM, MEID for CDMA).
You'll need the following permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
in order to do this.
That being said, be careful about doing this. Not only will users wonder why your application is accessing their telephony stack, it might be difficult to migrate data over if the user gets a new device.
Update: As mentioned in the comments below, this is not a secure way to authenticate users, and raises privacy concerns. It is not recommended. Instead, look at the Google+ Login API if you want to implement a frictionless login system.
The Android Backup API is also available if you just want a lightweight way to persist a bundle of strings for when a user resets their phone (or buys a new device).
In addition to the answer of Trevor Johns, you can use this as follows:
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.getDeviceId();
And you should add the following permission into your Manifest.xml file:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
In emulator, you'll probably get a like a "00000..." value. getDeviceId() returns NULL if device ID is not available.
I use the following code to get the IMEI or use Secure.ANDROID_ID as an alternative, when the device doesn't have phone capabilities:
/**
* Returns the unique identifier for the device
*
* #return unique identifier for the device
*/
public String getDeviceIMEI() {
String deviceUniqueIdentifier = null;
TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
if (null != tm) {
deviceUniqueIdentifier = tm.getDeviceId();
}
if (null == deviceUniqueIdentifier || 0 == deviceUniqueIdentifier.length()) {
deviceUniqueIdentifier = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
}
return deviceUniqueIdentifier;
}
Or you can use the ANDROID_ID setting from Android.Provider.Settings.System (as described here strazerre.com).
This has the advantage that it doesn't require special permissions but can change if another application has write access and changes it (which is apparently unusual but not impossible).
Just for reference here is the code from the blog:
import android.provider.Settings;
import android.provider.Settings.System;
String androidID = System.getString(this.getContentResolver(),Secure.ANDROID_ID);
Implementation note: if the ID is critical to the system architecture you need to be aware that in practice some of the very low end Android phones & tablets have been found reusing the same ANDROID_ID (9774d56d682e549c was the value showing up in our logs)
From: http://mytechead.wordpress.com/2011/08/28/how-to-get-imei-number-of-android-device/:
The following code helps in obtaining IMEI number of android devices :
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String device_id = tm.getDeviceId();
Permissions required in Android Manifest:
android.permission.READ_PHONE_STATE
NOTE: In case of tablets or devices which can’t act as Mobile Phone
IMEI will be null.
to get IMEI (international mobile equipment identifier)
public String getIMEI(Activity activity) {
TelephonyManager telephonyManager = (TelephonyManager) activity
.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getDeviceId();
}
to get device unique id
public String getDeviceUniqueID(Activity activity){
String device_unique_id = Secure.getString(activity.getContentResolver(),
Secure.ANDROID_ID);
return device_unique_id;
}
For Android 6.0+ the game has changed so i suggest you use this;
The best way to go is during runtime else you get permission errors.
/**
* A loading screen after AppIntroActivity.
*/
public class LoadingActivity extends BaseActivity {
private static final int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 0;
private TextView loading_tv2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loading);
//trigger 'loadIMEI'
loadIMEI();
/** Fading Transition Effect */
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
}
/**
* Called when the 'loadIMEI' function is triggered.
*/
public void loadIMEI() {
// Check if the READ_PHONE_STATE permission is already available.
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// READ_PHONE_STATE permission has not been granted.
requestReadPhoneStatePermission();
} else {
// READ_PHONE_STATE permission is already been granted.
doPermissionGrantedStuffs();
}
}
/**
* Requests the READ_PHONE_STATE permission.
* If the permission has been denied previously, a dialog will prompt the user to grant the
* permission, otherwise it is requested directly.
*/
private void requestReadPhoneStatePermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
// Provide an additional rationale to the user if the permission was not granted
// and the user would benefit from additional context for the use of the permission.
// For example if the user has previously denied the permission.
new AlertDialog.Builder(LoadingActivity.this)
.setTitle("Permission Request")
.setMessage(getString(R.string.permission_read_phone_state_rationale))
.setCancelable(false)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
//re-request
ActivityCompat.requestPermissions(LoadingActivity.this,
new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
})
.setIcon(R.drawable.onlinlinew_warning_sign)
.show();
} else {
// READ_PHONE_STATE permission has not been granted yet. Request it directly.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
}
/**
* Callback received when a permissions request has been completed.
*/
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == MY_PERMISSIONS_REQUEST_READ_PHONE_STATE) {
// Received permission result for READ_PHONE_STATE permission.est.");
// Check if the only required permission has been granted
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// READ_PHONE_STATE permission has been granted, proceed with displaying IMEI Number
//alertAlert(getString(R.string.permision_available_read_phone_state));
doPermissionGrantedStuffs();
} else {
alertAlert(getString(R.string.permissions_not_granted_read_phone_state));
}
}
}
private void alertAlert(String msg) {
new AlertDialog.Builder(LoadingActivity.this)
.setTitle("Permission Request")
.setMessage(msg)
.setCancelable(false)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do somthing here
}
})
.setIcon(R.drawable.onlinlinew_warning_sign)
.show();
}
public void doPermissionGrantedStuffs() {
//Have an object of TelephonyManager
TelephonyManager tm =(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
//Get IMEI Number of Phone //////////////// for this example i only need the IMEI
String IMEINumber=tm.getDeviceId();
/************************************************
* **********************************************
* This is just an icing on the cake
* the following are other children of TELEPHONY_SERVICE
*
//Get Subscriber ID
String subscriberID=tm.getDeviceId();
//Get SIM Serial Number
String SIMSerialNumber=tm.getSimSerialNumber();
//Get Network Country ISO Code
String networkCountryISO=tm.getNetworkCountryIso();
//Get SIM Country ISO Code
String SIMCountryISO=tm.getSimCountryIso();
//Get the device software version
String softwareVersion=tm.getDeviceSoftwareVersion()
//Get the Voice mail number
String voiceMailNumber=tm.getVoiceMailNumber();
//Get the Phone Type CDMA/GSM/NONE
int phoneType=tm.getPhoneType();
switch (phoneType)
{
case (TelephonyManager.PHONE_TYPE_CDMA):
// your code
break;
case (TelephonyManager.PHONE_TYPE_GSM)
// your code
break;
case (TelephonyManager.PHONE_TYPE_NONE):
// your code
break;
}
//Find whether the Phone is in Roaming, returns true if in roaming
boolean isRoaming=tm.isNetworkRoaming();
if(isRoaming)
phoneDetails+="\nIs In Roaming : "+"YES";
else
phoneDetails+="\nIs In Roaming : "+"NO";
//Get the SIM state
int SIMState=tm.getSimState();
switch(SIMState)
{
case TelephonyManager.SIM_STATE_ABSENT :
// your code
break;
case TelephonyManager.SIM_STATE_NETWORK_LOCKED :
// your code
break;
case TelephonyManager.SIM_STATE_PIN_REQUIRED :
// your code
break;
case TelephonyManager.SIM_STATE_PUK_REQUIRED :
// your code
break;
case TelephonyManager.SIM_STATE_READY :
// your code
break;
case TelephonyManager.SIM_STATE_UNKNOWN :
// your code
break;
}
*/
// Now read the desired content to a textview.
loading_tv2 = (TextView) findViewById(R.id.loading_tv2);
loading_tv2.setText(IMEINumber);
}
}
Hope this helps you or someone.
As in API 26 getDeviceId() is depreciated so you can use following code to cater API 26 and earlier versions
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String imei="";
if (android.os.Build.VERSION.SDK_INT >= 26) {
imei=telephonyManager.getImei();
}
else
{
imei=telephonyManager.getDeviceId();
}
Don't forget to add permission requests for READ_PHONE_STATE to use the above code.
UPDATE:
From Android 10 its is restricted for user apps to get non-resettable hardware identifiers like IMEI.
New Update:
For Android Version 6 And Above, WLAN MAC Address has been deprecated , follow Trevor Johns answer
Update:
For uniquely Identification of devices, You can Use Secure.ANDROID_ID.
Old Answer:
Disadvantages of using IMEI as Unique Device ID:
IMEI is dependent on the Simcard slot of the device, so it is not
possible to get the IMEI for the devices that do not use Simcard.
In Dual sim devices, we get 2 different IMEIs for the same device as it has 2 slots for simcard.
You can Use The WLAN MAC Address string (Not Recommended For Marshmallow and Marshmallow+ as WLAN MAC Address has been deprecated on Marshmallow forward. So you'll get a bogus value)
We can get the Unique ID for android phones using the WLAN MAC address also. The MAC address is unique for all devices and it works for all kinds of devices.
Advantages of using WLAN MAC address as Device ID:
It is unique identifier for all type of devices (smart phones and
tablets).
It remains unique if the application is reinstalled
Disadvantages of using WLAN MAC address as Device ID:
Give You a Bogus Value from Marshmallow and above.
If device doesn’t have wifi hardware then you get null MAC address,
but generally it is seen that most of the Android devices have wifi
hardware and there are hardly few devices in the market with no wifi
hardware.
SOURCE : technetexperts.com
The method getDeviceId() of TelephonyManager returns the unique device ID, for example, the IMEI for GSM and the MEID or ESN for CDMA phones. Return null if device ID is not available.
Java Code
package com.AndroidTelephonyManager;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.widget.TextView;
public class AndroidTelephonyManager extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView textDeviceID = (TextView)findViewById(R.id.deviceid);
//retrieve a reference to an instance of TelephonyManager
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
textDeviceID.setText(getDeviceID(telephonyManager));
}
String getDeviceID(TelephonyManager phonyManager){
String id = phonyManager.getDeviceId();
if (id == null){
id = "not available";
}
int phoneType = phonyManager.getPhoneType();
switch(phoneType){
case TelephonyManager.PHONE_TYPE_NONE:
return "NONE: " + id;
case TelephonyManager.PHONE_TYPE_GSM:
return "GSM: IMEI=" + id;
case TelephonyManager.PHONE_TYPE_CDMA:
return "CDMA: MEID/ESN=" + id;
/*
* for API Level 11 or above
* case TelephonyManager.PHONE_TYPE_SIP:
* return "SIP";
*/
default:
return "UNKNOWN: ID=" + id;
}
}
}
XML
<linearlayout android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android">
<textview android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="#string/hello">
<textview android:id="#+id/deviceid" android:layout_height="wrap_content" android:layout_width="fill_parent">
</textview></textview></linearlayout>
Permission Required
READ_PHONE_STATE in manifest file.
You can use this TelephonyManager TELEPHONY_SERVICE function to get unique device ID,
Requires Permission: READ_PHONE_STATE
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Example, the IMEI for GSM and the MEID or ESN for CDMA phones.
/**
* Gets the device unique id called IMEI. Sometimes, this returns 00000000000000000 for the
* rooted devices.
**/
public static String getDeviceImei(Context ctx) {
TelephonyManager telephonyManager = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
return telephonyManager.getDeviceId();
}
Return null if device ID is not available.
Try this(need to get first IMEI always)
TelephonyManager mTelephony = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(LoginActivity.this,Manifest.permission.READ_PHONE_STATE)!= PackageManager.PERMISSION_GRANTED) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mTelephony.getPhoneCount() == 2) {
IME = mTelephony.getImei(0);
}else{
IME = mTelephony.getImei();
}
}else{
if (mTelephony.getPhoneCount() == 2) {
IME = mTelephony.getDeviceId(0);
} else {
IME = mTelephony.getDeviceId();
}
}
} else {
IME = mTelephony.getDeviceId();
}
Use below code gives you IMEI number:
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
System.out.println("IMEI::" + telephonyManager.getDeviceId());
The method getDeviceId() is deprecated.
There a new method for this getImei(int)
Check here
You'll need the following permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
To get IMEI (international mobile equipment identifier) and if It is above API level 26 then we get telephonyManager.getImei() as null so for that, we use ANDROID_ID as a Unique Identifier.
public static String getIMEINumber(#NonNull final Context context)
throws SecurityException, NullPointerException {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imei;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
assert tm != null;
imei = tm.getImei();
//this change is for Android 10 as per security concern it will not provide the imei number.
if (imei == null) {
imei = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
} else {
assert tm != null;
if (tm.getDeviceId() != null && !tm.getDeviceId().equals("000000000000000")) {
imei = tm.getDeviceId();
} else {
imei = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
}
}
return imei;
}
For Android 10 Following code is working for me.
val uid: String = Settings.Secure.getString(ctx.applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
if (ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
imei = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
uid
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
telephonyManager.imei
}
else -> {
telephonyManager.deviceId
}
}
}
for API Level 11 or above:
case TelephonyManager.PHONE_TYPE_SIP:
return "SIP";
TelephonyManager tm= (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
textDeviceID.setText(getDeviceID(tm));
Kotlin Code for getting DeviceId ( IMEI ) with handling permission & comparability check for all android versions :
val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED) {
// Permission is granted
val imei : String? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) telephonyManager.imei
// older OS versions
else telephonyManager.deviceId
imei?.let {
Log.i("Log", "DeviceId=$it" )
}
} else { // Permission is not granted
}
Also add this permission to AndroidManifest.xml :
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!-- IMEI-->
use below code:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String[] permissions = {Manifest.permission.READ_PHONE_STATE};
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(permissions, READ_PHONE_STATE);
}
} else {
try {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
String imei = telephonyManager.getDeviceId();
} catch (Exception e) {
e.printStackTrace();
}
}
And call onRequestPermissionsResult method following code:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case READ_PHONE_STATE:
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
try {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
String imei = telephonyManager.getDeviceId();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Add following permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
For those looking for a Kotlin version, you can use something like this;
private fun telephonyService() {
val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
val imei = if (android.os.Build.VERSION.SDK_INT >= 26) {
Timber.i("Phone >= 26 IMEI")
telephonyManager.imei
} else {
Timber.i("Phone IMEI < 26")
telephonyManager.deviceId
}
Timber.i("Phone IMEI $imei")
}
NOTE: You must wrap telephonyService() above with a permission check using checkSelfPermission or whatever method you use.
Also add this permission in the manifest file;
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
There is no Way you can get imei number from andorid 10+ or 29+ mobiles here is the alternative function that will be used for creating imei number for devices.
public static String getDeviceID(){
String devIDShort = "35" + //we make this look like a valid IMEI
Build.BOARD.length()%10+ Build.BRAND.length()%10 +
Build.CPU_ABI.length()%10 + Build.DEVICE.length()%10 +
Build.DISPLAY.length()%10 + Build.HOST.length()%10 +
Build.ID.length()%10 + Build.MANUFACTURER.length()%10 +
Build.MODEL.length()%10 + Build.PRODUCT.length()%10 +
Build.TAGS.length()%10 + Build.TYPE.length()%10 +
Build.USER.length()%10 ; //13 digits
return devIDShort;
}
Restriction on non-resettable device identifiers
Starting in Android 10, apps must have the READ_PRIVILEGED_PHONE_STATE privileged permission in order to access the device's non-resettable identifiers, which include both IMEI and serial number.

Categories

Resources