is it possible to get the phonenumber of each device programmatically?
I tried this code:
TelephonyManager manager =(TelephonyManager)mAppContext.getSystemService(Context.TELEPHONY_SERVICE);
mPhoneNumber = manager.getLine1Number();
This works fine with some providers. Unfortunately it does not work with each provider. So i am looking for a trick or work around to get the phonenumber of the device. Is there a solution or is it impossible because the number is not stored on the sim card?
The method you are using is the only one part of the SDK to do this, and only works on devices where the number is stored on the SIM card, which only some carriers do. For all other carriers, you will have to ask the user to enter the phone number manually, as the number is simply not stored anywhere on the device from where you can retrieve it.
You can try to send specific SMS to ISP.
For example, in Beijing(China), when you send SMS "501" to 10001, you will get your phone number in the received message.
Then you only need to know how to send SMS and register a BroadcastReceiver to receive the message.
Now its not require any permission to get phone number
use Play Services API without the permission and hacks. Source and Full example.
build.gradle (version 10.2.x and higher required):
compile "com.google.android.gms:play-services-auth:$gms_version"
In your activity (the code is simplified):
enter image description here
#Override
protected void onCreate(Bundle savedInstanceState) {
// ...
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(Auth.CREDENTIALS_API)
.build();
requestPhoneNumber(result -> {
phoneET.setText(result);
});
}
public void requestPhoneNumber(SimpleCallback<String> callback) {
phoneNumberCallback = callback;
HintRequest hintRequest = new HintRequest.Builder()
.setPhoneNumberIdentifierSupported(true)
.build();
PendingIntent intent = Auth.CredentialsApi.getHintPickerIntent(googleApiClient,
hintRequest);
try {
startIntentSenderForResult(intent.getIntentSender(), PHONE_NUMBER_RC, null,
0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Logs.e(TAG, "Could not start hint picker Intent", e);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PHONE_NUMBER_RC) {
if (resultCode == RESULT_OK) {
Credential cred = data.getParcelableExtra(Credential.EXTRA_KEY);
if (phoneNumberCallback != null){
phoneNumberCallback.onSuccess(cred.getId());
}
}
phoneNumberCallback = null;
}
}
Related
I have implemented Phone number selector API in my project, now I want to check if entered umber is exist in mobile or not? it should proceed only when the device has that entered number. And also number should be inserted in first slot. How to do that?
Here is my code:
HintRequest hintRequest = new HintRequest.Builder()
.setHintPickerConfig(
new CredentialPickerConfig.Builder().setShowCancelButton(true).build()
)
.setPhoneNumberIdentifierSupported(true)
.build();
PendingIntent intent = Credentials.getClient(Register.this).getHintPickerIntent(hintRequest);
try {
startIntentSenderForResult(intent.getIntentSender(),CREDENTIAL_REQUEST,null,0,0,0,new Bundle());
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
enterNumber = findViewById(R.id.renter_number);
rback_btn = findViewById(R.id.rback_btn);
rback_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
Intent i = new Intent(getApplicationContext(), Welcome.class);
startActivity(i);
}
});
next = findViewById(R.id.nextbtn_r);
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
strnumber = enterNumber.getText().toString();
String otp= new DecimalFormat("000000").format(new Random().nextInt(999999));
Intent intent = new Intent(getApplicationContext(), Verification.class);
intent.putExtra("Your OTP is:",otp);
intent.putExtra("Number:",strnumber);
startActivity(intent);
}
});
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CREDENTIAL_REQUEST && resultCode == RESULT_OK) {
//obtain the phone number from the result
Credential credential = data.getParcelableExtra(Credential.EXTRA_KEY);
enterNumber.setText(credential.getId().substring(3));
Toast
.makeText(context, "Mob"+credential.getId().substring(3), Toast.LENGTH_SHORT)
.show();
} else if (
requestCode == CREDENTIAL_REQUEST
&& requestCode == CredentialsApi.ACTIVITY_RESULT_NO_HINTS_AVAILABLE
) {
Toast
.makeText(context, "No Phone Numbers found!", Toast.LENGTH_SHORT)
.show();
}
}
getting phone number isn't possible on Android. there is a method:
TelephonyManager mgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String phoneNumber = mgr.getLine1Number();
that should work only with permission:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
but thats not reliable with nowadays SIM cards... in fact most of devices will return null. you can check this in system Settings -> About -> Phone Identinty (or Phone number)
note that SIM card itself does have some identity params, like serial number, but it is NOT storing own number, it is attached to SIM card on network side. thats why most of phone number validation services are asking for entering phone number, then sending SMS and asking for re-writting code (or you can do it programmatically - after requesting validating SMS sending just check incoming SMSes in next few secs/mins, and you will need a permission for that)
I am new to android dev and little knowledge of java.I want to know how to inflate a layout from service using SYSTEM_ALERT_WINDOW
public void checkDrawOverlayPermission() {
/* check if we already have
permission to draw over
other apps */
if(android.os.Build.VERSION.SDK_INT > 23) {
if (!Settings.canDrawOverlays(this))
{
/* if not construct intent to request permission */
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
/* request permission via start activity for result */
startActivityForResult(intent, REQUEST_CODE);
}
else {
createOnTopView();
}}}}
I used that to get permission↑↑↑
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
/* check if received result code
is equal our requested code for draw permission */
if (requestCode == REQUEST_CODE && android.os.Build.VERSION.SDK_INT > 22) {
/* if so check once again if we have permission */
if (Settings.canDrawOverlays(this)) {
createOnTopView();
}
}
}
after I run this on my phone Teckno k7 ,android 6.0
It runs well buh can't run on my friend's phone Techno F2.it crashes on his phone.
Please help me.
I'm trying to use the DriveApi in order to create some folders and upload a text file with some data for a user.
I've tried implementing the quick-start guide from (link), but it has a few fundamental issues:
The api gets connected at onResume so the user will get prompted to give access to the app immediately after he opens the app which is confusing and scary.
If you deny or press the back button at the consent screen, the onResume method will get called again and the consent screen will be shown one more time, leading to an infinite loop.
I would rather like to connect the api when the user actually needs to store data so that will make more sense to the user. I tried doing it like this:
ResultCallback<DriveFolder.DriveFolderResult> folderCreatedCallback = new
ResultCallback<DriveFolder.DriveFolderResult>() {
#Override
public void onResult(#NonNull DriveFolder.DriveFolderResult result) {
clearCurrentAction();
if (!result.getStatus().isSuccess()) {
Log.e(TAG, "Error while trying to create the folder");
return;
}
Log.d(TAG, "Created a folder: " + result.getDriveFolder().getDriveId());
}
};
public DriveApiHelper(GoogleApiClient mGoogleApiClient) {
this.mGoogleApiClient = mGoogleApiClient;
}
public void createBackupsFolder() {
currentAction = DriveActions.CREATING_FOLDER;
if (mGoogleApiClient.isConnected()) {
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("test").build();
Drive.DriveApi.getRootFolder(mGoogleApiClient).createFolder(
mGoogleApiClient, changeSet).setResultCallback(folderCreatedCallback);
} else {
mGoogleApiClient.connect();
}
}
and this is how my onResume and onConnected methods look like:
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
// Create the API client and bind it to an instance variable.
// We use this instance as the callback for connection and connection
// failures.
// Since no account name is passed, the user is prompted to choose.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
mDriveHelper = new DriveApiHelper(mGoogleApiClient);
}
//Log.d(TAG, mDriveHelper.getCurrentAction() + "");
Log.d("test", "Connected " + mGoogleApiClient.isConnected());
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "API client connected.");
switch (mDriveHelper.getCurrentAction()) { //resume the last action
case CREATING_FOLDER:
mDriveHelper.createBackupsFolder();
break;
}
}
I was hoping that keeping a reference of what the user tried to do when the api was asked to connect, I can resume that action after the api successfully connected. This is the closest implementation I've got to fit my needs, but after actually clicking the 'Allow' button from the consent screen none of the api callbacks gets called (onConnected, onConnectionFailed).
I actually need to call the connect method one more time in order to get connected and also fire the onConnected successfully resuming the users' action.
Turns out that I forgot about overriding onActivityResult (it wasn't mentioned in the documentation at that time and I don't know if they included it now)
Just add:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_CODE_RESOLUTION) {
mGoogleApiClient.connect();
}
} else {
if (requestCode == REQUEST_CODE_RESOLUTION) {
mDriveHelper.dismissStatusDialog();
}
}
}
I am working on restoring SMS on KITKAT. Referring to this article I have added the things which are required to set my app as default app for SMS. After adding all required things in manifest file I have write the following code:
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
mDefaultSmsApp = Telephony.Sms.getDefaultSmsPackage(mContext);
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, mContext.getPackageName());
mContext.startActivity(intent);
}
The above code shows this dialog but I am unable to get the result from this activity/dialog either user clicked on Yes or No because I want to add listener or get any code which should represent that the user clicked on these buttons.
Thanks.
One way to do this is to fire the Intent with startActivityForResult(), and then check the resultCode in the onActivityResult() method. Please note that I've changed the code in the example to run in an Activity's Context.
private static final int DEF_SMS_REQ = 0;
private String mDefaultSmsApp;
...
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
mDefaultSmsApp = Telephony.Sms.getDefaultSmsPackage(this);
if (!getPackageName().equals(mDefaultSmsApp))
{
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName());
startActivityForResult(intent, DEF_SMS_REQ);
}
}
...
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch (requestCode)
{
case DEF_SMS_REQ:
boolean isDefault = resultCode == Activity.RESULT_OK;
...
}
}
As mentioned in a comment below, apparently checking the result code is not 100% reliable. A safer check is to simply compare your app's package name to the current default in onActivityResult(). There's no need to check the result code at all, like the answer linked in the comment shows.
String currentDefault = Sms.getDefaultSmsPackage(this);
boolean isDefault = getPackageName().equals(currentDefault);
The way you can react on "yes" button click:
private String mDefSmsPackage;
#Override
public void onCreate(#Nullable Bundle state) {
//...
mDefSmsPackage = Telephony.Sms.getDefaultSmsPackage(getActivity())
}
#Override
public void onResume() {
super.onResume();
String newDefSmsPkg = Telephony.Sms.getDefaultSmsPackage(getActivity());
if (!TextUtils.equals(mDefSmsPackage, newDefSmsPkg)) {
mDefSmsPackage = newDefSmsPkg;
//ON DEF SMS APP CAHNGE...
}
}
I am trying to build an alarm application. When the alarm turns on, the user has to scan a matching QR code before it is turned off. I've taken a look at this link to get the sound playing: How to play ringtone/alarm sound in Android and I am using the ScanningViaIntent from the zxing library for the QR code scanner: https://code.google.com/p/zxing/.
So I start the sound in the onStart() activity:
#Override
public void onStart(){
super.onStart();
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
The user then starts the scanner by pressing a button:
private class HandleClick implements OnClickListener{
public void onClick(View arg0) {
IntentIntegrator integrator = new IntentIntegrator(AlarmRequirementsActivity.this);
integrator.initiateScan();
}
}
The result of the scanner is returned here:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanResult != null) {
System.out.println("scanREsult" + scanResult);
System.out.println("requestCode: " + requestCode);
TextView result =(TextView)findViewById(R.id.scanResult);
if (resultCode == RESULT_OK) {
String scanResultString = intent.getStringExtra("SCAN_RESULT");
if(scanResultString .equals(matchString))
{
result.setText("You found it!");
r.stop();
}
else
{
result.setText("\"" + scanResultString + "\""+ " did not match");
}
System.out.println(intent.getStringExtra("SCAN_RESULT"));
} else if (resultCode == RESULT_CANCELED) {
}
}
// else continue with any other code you need in the method
}
As you can see, I call r.stop() after a successful match. However these are my problems:
The activity is restarted after coming back from the scanner. It doesn't matter if the match was successful or not.
This results in two alarm tones being played now
I've tried putting it in the onCreate() method but to no avail as well.
UPDATE:
I've tried:
#Override
public void onStart(){
super.onStart();
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
r = RingtoneManager.getRingtone(getApplicationContext(), notification);
if(!r.isPlaying())
{
r.play();
}
}
and this below. Both of which with the same problems
if(scanResultString .equals(matchString))
{
result.setText("You found it!");
if(r.isPlaying())
{
r.stop();
}
}
The activity is restarted after coming back from the scanner. It doesn't matter if the match was successful or not.
I assume that you need to start another activity to do the scan, which means that your activity will (at least) need to be paused and more likely stopped to allow that other activity to run (as per the Android activity lifecycle).
Therefore, you will have to expect onStart() to be called when returning from the scanner.
This results in two alarm tones being played now
You should be able to avoid this and your code to check if the ringtone is already playing seems like a good start. However, I suspect you are creating a new ringtone object each time onStart() is executed.
It is hard for me to guess at all of the things you will need to do to fully resolve your problems (not to mention problems you will only see when your activity is fully recreated by Android - for example when the screen orientation changes - as this needs further handling in your code; see the Android doc for the activity lifecycle, particularly onSaveInstanceState()).
My guess at the next step would be to move the line:
r = RingtoneManager.getRingtone(getApplicationContext(), notification);
into your onCreate() method. My hope is that this, combined with the if (!r.isPlaying()) code should prevent the double-alarm issue in most cases.