I can get the phone number from some old SIM card by using TelephonyManager.getLine1Number(), but it's not working for some new SIM card.
I tried to use this code snippet, but it's also not working. It just return empty string.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<SubscriptionInfo> subscription = SubscriptionManager.from(getApplicationContext()).getActiveSubscriptionInfoList();
for (int i = 0; i < subscription.size(); i++) {
SubscriptionInfo info = subscription.get(i);
Log.d(TAG, "number " + info.getNumber());
}
}
Is there another way to know the phone number programmatically, I even think to send a real SMS to another device, and this device can receive and get the phone number and send to server backend. But it's a bit troublesome, is there any simpler solution?
Related
I have implemented an app which will allow user to connect to a desired network.
If the SSID record is already remembered by phone. It will notify user to manually delete the SSID record.
Here is some sample code
temp = -1;
for (int i = 0; i < WiFi.ConfiguredNetworks.Count; i++)
{
if (String.Compare(WiFi.ConfiguredNetworks[i].Ssid, ("\"" + SSID + "\"")) == 0)
{
temp = WiFi.ConfiguredNetworks[i].NetworkId;
break;
}
}
if(temp != -1) //This SSID is already remembered by phone
{
bool success = WiFi.RemoveNetwork(temp)
if(success == false)
{
//Call some function to notify user to manually remove the network
}
}
Things happened at //Call some function to notify user to manually remove the network.
Sometimes the user goes to the wifi system page. They found out that there is no record of this SSID.
In my opinion, if RemoveNetwork() return failed, that means this SSID is already remembered by phone.
And it is not build by the current app.
Is that wrong?
Issue happened on device Nokia 8(Android 9).
As the docs for WifiManager say:
Compatibility Note: For applications targeting Build.VERSION_CODES.Q or above, this API will always fail and return false.
If your API level is below 29 then you probably aren't passing a valid NetworkId.
So I am developing an app which works as device owner on the specific Android device. This app is not available on the play store, but gets transferred with a provisioning app from a different device via NFC. Since those devices will be very specific to certain tasks (scanning NFC tags), I want to enable and disable a few things from the very beginning.
I want to disable sound:
devicePolicyManager.setMasterVolumeMuted(adminComponentName, true);
But this doesn't seem to work at all, but no exception either.
But what I really want to do is enabling mobile Data and Roaming, the SIM cards which we are using support that.
devicePolicyManager.setSecureSetting(adminComponentName, Settings.Global.DATA_ROAMING, String.valueOf(1));
devicePolicyManager.setSecureSetting(adminComponentName,"mobile_data",String.valueOf(1));
But sadly, those two lines of code throw a security exception:
java.lang.SecurityException: Permission denial: Device owners cannot update mobile_data
Interestingly, inserting APNs work (later in the code) Any chance to be able to turn on mobile data and data roaming as a device admin/owner? I mean, thats the whole purpose of being a device admin, right?
Here is the full code for reference: (the parts which make the app crash are commented out)
public static void enableRestrictedAppsAndSettings(Activity activity) {
ComponentName adminComponentName = DeviceAdminReceiver.getComponentName(activity);
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// disable keyguard and sound
devicePolicyManager.setKeyguardDisabled(adminComponentName, true);
devicePolicyManager.setMasterVolumeMuted(adminComponentName, true);
devicePolicyManager.setSecureSetting(adminComponentName, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY));
//devicePolicyManager.setSecureSetting(adminComponentName, Settings.Global.DATA_ROAMING, String.valueOf(1));
//devicePolicyManager.setSecureSetting(adminComponentName,"mobile_data",String.valueOf(1));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (devicePolicyManager.isDeviceOwnerApp(activity.getApplicationContext().getPackageName())) {
devicePolicyManager.enableSystemApp(adminComponentName,"com.sec.android.app.camera");
devicePolicyManager.clearUserRestriction(adminComponentName, UserManager.DISALLOW_DATA_ROAMING);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
L.debug("KIOSK", "APN");
ApnSetting apn;
TelephonyManager manager = (TelephonyManager)activity.getSystemService(Context.TELEPHONY_SERVICE);
if (manager.getSimState() == TelephonyManager.SIM_STATE_READY) {
String mcc = manager.getSimOperator().substring(0, 3);
String mnc = manager.getSimOperator().substring(3);
L.debug("KIOSK " + mcc + " "+mnc);
apn = new ApnSetting.Builder()
.setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
.setApnName("em")
.setEntryName("em")
.setOperatorNumeric(mcc + mnc) // this is a must its consists from Telephony.Carriers.MCC + Telephony.Carriers.MNC, In my case, I had to pad the MNC with a leading zero
.setProtocol(ApnSetting.PROTOCOL_IPV4V6) // this is a must
.setRoamingProtocol(ApnSetting.PROTOCOL_IPV4V6) // this is a must
.setCarrierEnabled(true)
.build();
devicePolicyManager.removeOverrideApn(adminComponentName,0);
devicePolicyManager.addOverrideApn(adminComponentName, apn);
devicePolicyManager.setOverrideApnsEnabled(adminComponentName, true);
}
}
}
}
Unfortunately the device owner has no access to mobile data status (you're right, weird restriction for the device owner app!).
However, you can still get the mobile data status and force the user to turn it on or off if the status is wrong. Here're the code samples (thanks to Test if background data and packet data is enabled or not).
public static boolean isMobileDataEnabled(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
try {
Class clazz = Class.forName(cm.getClass().getName());
Method method = clazz.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true); // Make the method callable
// get the setting for "mobile data"
return (Boolean) method.invoke(cm);
} catch (Exception e) {
// Let it will be true by default
return true;
}
}
This code works on Android 5-9 (not tested on Android 10 yet).
So you run a background service which performs this check once per some seconds and requires the user to turn on/off the mobile data in the status bar.
You can see how it is done by cloning this open source Android MDM (this is my project). The method is here: Utils.isMobileDataEnabled(Context context).
In my Android application, I need to display phone numbers of the Sim cards which are available in the device.
I tried with the below codes
private String getPhone() {
TelephonyManager phoneMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(activity, wantPermission) != PackageManager.PERMISSION_GRANTED) {
return "";
}
return phoneMgr.getLine1Number();
}
and
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
List<SubscriptionInfo> subscription = SubscriptionManager.from(getApplicationContext()).getActiveSubscriptionInfoList();
for (int i = 0; i < subscription.size(); i++) {
SubscriptionInfo info = subscription.get(i);
Log.d(TAG, "number " + info.getNumber());
Log.d(TAG, "network name : " + info.getCarrierName());
Log.d(TAG, "country iso " + info.getCountryIso());
}
}
But both are returning null or empty string only.
I have added the manifest permission also.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Could you please help me.
Thanks.
some phone companies not give this permission to get number from sim-card because i was same problem in past projects.
(in the past project i want to send OTP on simcard number user can't type his number. it was for security purpose.)
so some of phone gives you output correct and remains give you output as NULL
I'm Trying the following code to get System phone number
TelephonyManager tMgr =(TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
mPhoneNumber = tMgr.getLine1Number();
But it is not working.
In my phone, i use
Settings->About Phone-->Status-Phone Number
is there a simple app i can use ? , I m writing from Turkey. does sim card make a difference ?
Not all telecom carriers store the phone number on the SIM card. The approach you are using only works if the SIM card in the device has the mobile number stored on it.
If you cannot see your phone number in the mobile settings, then it means that it isn't stored on the SIM card. You will have to manually ask the user to enter it into your app if you absolutely need it. There is no other way.
You can try something like this. It works perfectly.
public String getPhoneNumber(Context context) {
TelephonyManager mTelephonyMgr;
mTelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String num = mTelephonyMgr.getLine1Number();
return fillPhoneNumber(num);
}
private String fillPhoneNumber(String num) {
try{
if (num != null && num.length() > 0) {
if (num.length() >= 9) {
num = num.replaceAll("\\D", "");
if (num.substring(0, 1).equals("8")) {
num = "+3" + num;
} else if (num.substring(0, 1).equals("0")) {
num = "+38" + num;
} else if (num.substring(0, 1).equals("3")) {
num = "+" + num;
}
}
return num;
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
Note: Not all phones return a phone number.
There is no deterministic way to find the MSISDN. The above approach only works if SIM has stored the MSISDN. Other work around is to retrieve the number from facebook. It also may or may not work.
The only sure shot way is to create account with some SMS gateway provider like http://trumpia.com, then send SMS to the toll free number, and then call the API to retrieve the MSISDN.
Is there a way that I can access the other sim in my android? I have an android Cherry Mobile Orbit which is a dual sim android phone. I want to develop an SMS application for my phone, but only the 1st sim will be access. I want to access the other sim, so that when i press enter to send the message, there will be a prompt, that which sim the message will be sent.
I know that it's propreitary, but the phone manufacturer has no feedback about it. Is there any other way? tweaking or something?
I think you can use dex2jar or apktool to reverse those app which runs on dual sim card devices, once you found the related "service manager", "telephony manager",some interface stub, or some key words like "Gemini" you can then use Java Reflection, reflects all of method of this class. Then you can achieve this goal.
This method can be used to select one SIM from 2 SIMs!
//above Android API 22
if (Build.VERSION.SDK_INT > 22) {
//for dual sim mobile
SubscriptionManager localSubscriptionManager = SubscriptionManager.from(this);
if (localSubscriptionManager.getActiveSubscriptionInfoCount() > 1) {
//if there are two sims in dual sim mobile
List localList = localSubscriptionManager.getActiveSubscriptionInfoList();
SubscriptionInfo simInfo = (SubscriptionInfo) localList.get(0);
SubscriptionInfo simInfo1 = (SubscriptionInfo) localList.get(1);
final String sim1 = simInfo.getDisplayName().toString();
final String sim2 = simInfo1.getDisplayName().toString();
}else{
//if there is 1 sim in dual sim mobile
TelephonyManager tManager = (TelephonyManager) getBaseContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String sim1 = tManager.getNetworkOperatorName();
}
}else{
//below android API 22
TelephonyManager tManager = (TelephonyManager) getBaseContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String sim1 = tManager.getNetworkOperatorName();
}
Then to send an SMS you can use the below method
public static boolean sendSMS(Context context, String smsText) {
SmsManager smsMan = SmsManager.getDefault();
SharedPreferences prefs = context.getSharedPreferences("uinfo", MODE_PRIVATE);
String sim = prefs.getString("sim", "No name defined");
String simName = prefs.getString("simName", "No name defined");
String toNum = "";
try {
if (Build.VERSION.SDK_INT > 22) {
SubscriptionManager localSubscriptionManager = SubscriptionManager.from(context);
if (localSubscriptionManager.getActiveSubscriptionInfoCount() > 1) {
int simID = Integer.parseInt(sim);
List localList = localSubscriptionManager.getActiveSubscriptionInfoList();
SubscriptionInfo simInfo = (SubscriptionInfo) localList.get(simID);
ArrayList<String> parts = smsMan.divideMessage(smsText);
SmsManager.getSmsManagerForSubscriptionId(simInfo.getSubscriptionId()).sendMultipartTextMessage(toNum, null, parts, null, null);
}else{
ArrayList<String> parts = smsMan.divideMessage(smsText);
smsMan.sendMultipartTextMessage(toNum, null, parts, null, null);
}
return true;
}else{
ArrayList<String> parts = smsMan.divideMessage(smsText);
smsMan.sendMultipartTextMessage(toNum, null, parts, null, null);
}
} catch (Exception e) {
}
return false;
}
Officially right now there is no API to support this, you have to contact the device manufacturer.
Assuming that you are developing the app for your own phone, and you are willing to go through the trouble of finding out the IDs (sim_id) assigned to each of your SIM cards (probably via checking the phone's log outputs, searching for sim_id, which was what I did), you can use the following code to set the default SIM for SMS sending:
int simId = <place desired SIM ID here>;
Intent simIntent = new Intent("android.intent.action.SMS_DEFAULT_SIM");
simIntent.putExtra("simid", simId);
sendBroadcast(simIntent);
Combined with some other UI prompt stuff (for actually 'picking' the preferred SIM), this should do the trick.
I'm not at all sure if this approach would work for you (although the code seems quite 'standard'); I figured it out with trial and error on my Mlais MX28 (with a customized ROM). But it's still worth a shot, I suppose. :)
UPDATE:
Strangely, the solution stopped working unexpectedly after a few updates to the app I was working on. But I came across another way (which seems to be more promising). (I believe this can be extended for other SIM selection scenarios as well, as the settings cache contains entries with names gprs_connection_sim_setting, voice_call_sim_setting, video_call_sim_setting and the like.)
ContentValues val = new ContentValues();
val.put("value", "here goes the preferred SIM ID");
getContentResolver().update(Uri.parse("content://settings/system"), val, "name='sms_sim_setting'", null);
(Unfortunately, this requires the android.permission.WRITE_SETTINGS permission.)