I want to make a call when the TelephonyManager state IDLE detects a true value on CallEnded variable.
The first call goes normally, but when changes from OFFHOOK to IDLE I need a new call intent to be performed, but there is no call showing up.
What I'm missing ?
Thanks for your time.
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.support.v4.app.ActivityCompat;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Boolean CallEnded = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TelephonyManager telephoneM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener listener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
if(CallEnded){
performDial();
}
break;
case TelephonyManager.CALL_STATE_RINGING:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
CallEnded=true;
}
}
};
telephoneM.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
performDial();
}
});
}
private void performDial() {
Intent dial = new Intent(Intent.ACTION_CALL);
dial.setData(Uri.parse("tel:911"));
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
return;
}
}
Manifest
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
First issue is that you're not allowed to ACTION_CALL an emergency number like 911 of you're not a system app.
The intent will be converted to an ACTION_DIAL intent, causing the system phone app to appear and allow the user to manually call the number if she chooses to.
I would try first with a standard phone number to make sure this is not the issue.
Second issue is related to calling the same intent twice on Android.
In certain cases Android might detect the exact same intent, and will simply ignore the new one.
If that might be the issue, try adding some constantly changing value to your url's data, like:
Intent dial = new Intent(Intent.ACTION_CALL);
dial.setData(Uri.parse("tel:212-555-1234" + "?time=" + System.currentTimeMillis()));
Related
In my app, I want to get the battery level in the background because I want to announce it in the text to speech when the battery level is low or when the battery is full or at any level. I have used the broadcast receivers and can get the battery level but don't know how to get it in the background.
Anyone can help?
The thing that you want to achieve can be done via intent Service, if you dig in the docs you can find it yourself, here is the link Intent Service, This type of intent can be fired in the background and can be used to perform various simple operations such as yours, because they don't have any interface but rather just operations executed in background.
Also here is a video guide Background Services which you can use for yourself to get battery percentage and announce it after a certain condition
Edit 2:
(Nothing Required in XML as this is a background process/operation)
This is a code to get the battery percentage and announce it using Text to speech in broadcast receiver,
MainActivity.java
package com.example.text_to_speech;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent=new Intent(this,myBackgroundProcess.class);
intent.setAction("BackgroundProcess");
PendingIntent pendingIntent=PendingIntent.getBroadcast(this,0,intent,0);
AlarmManager alarmManger= (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManger.setRepeating(AlarmManager.RTC_WAKEUP,0,10,pendingIntent);//change this time based on your liking which will fire the intent
}
}
customerclass- myBackgroundProcess.java
package com.example.text_to_speech;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import java.util.Locale;
import static android.content.Context.BATTERY_SERVICE;
public class myBackgroundProcess extends BroadcastReceiver {
private TextToSpeech mTTS;
#Override
public void onReceive(Context context, Intent intent) {
mTTS = new TextToSpeech(context.getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
int result = mTTS.setLanguage(Locale.US);
if (result == TextToSpeech.LANG_MISSING_DATA
|| result == TextToSpeech.LANG_NOT_SUPPORTED) {
Log.e("TTS", "Language not supported");
} else {
BatteryManager bm = (BatteryManager) context.getSystemService(BATTERY_SERVICE);
int batLevel = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
if(batLevel==100 || batLevel<=10 || batLevel==50)
speak(context,batLevel);
}
} else {
Log.e("TTS", "Initialization failed");
}
}
});
}
public void speak(Context context, int batlevel)
{
mTTS.setPitch(10);
mTTS.setSpeechRate(1);
String text=String.valueOf(batlevel);
mTTS.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
}
In Android Manifest Register the receiver and add intent filter to it as shown below (below application tag)
<receiver android:name=".myBackgroundProcess"
android:enabled="true"
android:exported="true"
>
<intent-filter>
<action android:name="BackgroundProcess"/>
</intent-filter>
</receiver>
This is the code I used to do my work, but unfortunately It doesn't work for my device with Android Pie(9.0). But It works for device with Android Naugat(7.0). I already enabled the phone permission for the app using device App Settings. Can you give me a solution for this?
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if(extras!=null){
String state = extras.getString(TelephonyManager.EXTRA_STATE);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
String phoneNo = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context, "You Got A Call From " + phoneNo, Toast.LENGTH_SHORT).show();
}
}
}
}
I just started with Java and Android coding. I wrote an application for a scientific study in my university. The app is for a local exhibition of a museum. I have different locations in my town, each location with its own exhibit.
Now I made an activity for each of the locations, so the user can see some useful information of the sample. Now I want to combine the app with iBeacons, I bought 6 beacons from Estimote. As I am not really experienced with this, I hope you can help with a point to start off?
I want the app to give the user a notification with some text like: "You are in front of object XY. Tap to see more information." After tapping on the notification the user should open the specific activity which I created. I also want the app to search for beacons in the background, so if the user comes close to a location, he/she gets automatically a notification after a few seconds.
I already read a post, but I could not really figure out how to use it correctly:
Estimote iBeacon: Monitoring in background (Android)
A broad answer to a broad question: We did exactly that type of application for a museum here in Finland using our Proximi.io platform. You can of course hardcode the beacons, actions and content into the application by e.g. using the Estimote SDK. The benefit of using an external portal/backend is that you don't have to update the entire app whenever the museum exhibition changes. In the best scenario, the museum itself could be in charge of updating the exhibit info, when they wish. If you're interested, Proximi.io is now in open beta, and it's free and super simple to use.
The free and open source Android Beacon Library has a reference application that launches an activity the first time a beacon is seen. You can see the line of code that launches the Activity here.
In order to modify this to do what you want, you would need to make a different Region object for each museum location, initializing it with its beacon identifiers. You'd put this in the Application onCreate method like this:
Region museumLocation1 = new Region("museumLocation1", Identifier.parse("2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6"), Identifier.parse("1"), Identifier.parse("1"));
Region museumLocation2 = new Region("museumLocation2", Identifier.parse("2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6"), Identifier.parse("1"), Identifier.parse("2"));
List regionList = Arrays.asList(new Region[] {museumLocation1, museumLocation2} );
regionBootstrap = new RegionBootstrap(this, regionList);
Then you can modify the didEnterRegion method in that same class to launch different activities for each beacon like this:
if (region.getUniqueId().equals("museumLocation1")) {
Intent intent = new Intent(this, Museum1Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
if (region.getUniqueId().equals("museumLocation2")) {
Intent intent = new Intent(this, Museum2Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
so now I played a little bit with the code and this is my MainActivity for now.
But I think I am not done yet. The problem is also, that the app not recognizes the region variable in the didEnterRegion - method.
package com.example.walter.him;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Handler;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.app.Application;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends ActionBarActivity implements BootstrapNotifier
{
private static final String TAG = "AndroidProximityReferenceApplication";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private andreasplatz monitoringActivity = null;
private hagentor monitoringActivity2 = null;
Typeface segoe_wp, times;
private static Button liste, info, about_us;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
liste = (Button) findViewById(R.id.liste);
info = (Button) findViewById(R.id.info);
about_us = (Button) findViewById(R.id.about_us);
segoe_wp = Typeface.createFromAsset(getAssets(), "fonts/segoe_wp.ttf");
times = Typeface.createFromAsset(getAssets(), "fonts/times.ttf");
liste.setTypeface(segoe_wp);
info.setTypeface(segoe_wp);
about_us.setTypeface(segoe_wp);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setLogo(R.drawable.ic_launcher);
getSupportActionBar().setDisplayUseLogoEnabled(true);
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
Region museumLocation1 = new Region("museumLocation1", Identifier.parse("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), Identifier.parse("56170"), Identifier.parse("42307"));
Region museumLocation2 = new Region("museumLocation2", Identifier.parse("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), Identifier.parse("55787"), Identifier.parse("12089"));
List regionList = Arrays.asList(new Region[]{museumLocation1, museumLocation2});
regionBootstrap = new RegionBootstrap(this, regionList);
backgroundPowerSaver = new BackgroundPowerSaver(this);
onClickOpenInfo();
onClickOpenListe();
onClickOpenAbout();
}
public void didEnterRegion(Region arg0) {
// Cannot resolve symbol 'region'
if (region.getUniqueId().equals("museumLocation1")) {
Intent intent = new Intent(this, andreasplatz.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
if (region.getUniqueId().equals("museumLocation2")) {
Intent intent = new Intent(this, hagentor.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent);
}
haveDetectedBeaconsSinceBoot = true;
}
#Override
public void didExitRegion(Region region) {
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("An beacon is nearby.")
.setSmallIcon(R.drawable.ic_launcher);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, andreasplatz.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(andreasplatz activity) {
this.monitoringActivity = activity;
}
public void onClickOpenInfo()
{
info = (Button)findViewById(R.id.info);
info.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent openInfo = new Intent("com.example.walter.him.info_ausstellung");
startActivity(openInfo);
}
}
);
}
public void onClickOpenListe()
{
liste = (Button) findViewById(R.id.liste);
liste.setOnClickListener(
new View.OnClickListener()
{
public void onClick (View v)
{
Intent openListe = new Intent("com.example.walter.him.liste_orte");
startActivity(openListe);
}
}
);
}
public void onClickOpenAbout()
{
about_us = (Button) findViewById(R.id.about_us);
about_us.setOnClickListener(
new View.OnClickListener()
{
public void onClick (View v)
{
Intent openAbout = new Intent("com.example.walter.him.about_us");
startActivity(openAbout);
}
}
);
}
}
I Have a BroadcastReceiver set up to turn Bluetooth on and off according to power state (when plugged in, bluetooth is on, unplugged, bluetooth is off). This is working just fine (yay!). however, my very simple app has a single button, which also turns Bluetooth on and off, and has the text "Bluetooth on" or "Bluetooth Off", as applicable. I would like to update this single button, BUT, I only have to update it if the app is in the foreground.
Inside onResume on m,y main activity, I'm calling my updateUI method, which checks the Bluetooth state, and updates the button accordingly. however, that only applies if the program was open and in the background, and is resumed, NOT if i'm in the program while plugging/unplugging the power.
I created a new activity (CheckIfAppIsRunningActivity.java) with this code which is supposed to check if my app is running in the foreground, and if so, take it to the activity (BluetoothOnActivity) which will update the button:
package vermel.BluetoothOn;
import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class CheckIfAppIsRunningActivity extends Activity{
public void onCreate() {
checkStatus();
}
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it);
}
};
public void checkStatus() {
ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningProcInfo = activityManager.getRunningAppProcesses();
for(int i = 0; i < runningProcInfo.size(); i++){
if(runningProcInfo.get(i).processName.equals("vermel.BluetoothOn")) {
if (runningProcInfo.get(i).lru == RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
//start activity
/* Intent it = new Intent();
it.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.BluetoothOnActivity");
context.startActivity(it); */
}
}
}
}
}
and i'm pointing to it from my broadcast receiver:
package vermel.BluetoothOn;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Button;
import android.widget.Toast;
public class BTDetector extends BroadcastReceiver {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
public void onReceive(Context context , Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
//TODO if app is open, change text on button to on
//Toast.makeText(context, "turned on bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
} else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
if (mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.disable();
//TODO if app is open, change text on button to off
//Toast.makeText(context, "turned off bluetooth", Toast.LENGTH_LONG).show();
Intent i = new Intent();
i.setClassName("vermel.BluetoothOn", "vermel.BluetoothOn.CheckIfAppIsRunningActivity");
context.startActivity(i);
}
}
}
}
a few things: yes, I know i'm not supposed to use .enable() without user permission. in a weird way, plugging in the phone IS my user permission, since this is ALL that this app does, so, it's not sneaky, since you know what you're getting when you're installing the app.
The commented stuff is mostly things i've tried in vain..
I'm very open to the fact that i'm making this WAY harder than I need to...
so, as i said, it does turn Bluetooth on and off beautifully, but simply crashes after that. I can't debug it, since the emulator doesn't have Bluetooth , and i'm disconnecting the phone to get the crash result, so, it's not logging anything, since it's now connected...
I'm new in both Java and Android, and would appreciate a bit of patience. I try reading the official android documentation, but that's like chinese to me... so, an extended explanation would be great...
Thanks for reading!
My requirement is to turn on speakerphone whenever an outgoing call is initiated. I tried the following code, but it is not working. In fact, speakerphone turns on when in the middle of a call, a second call comes !
package in.co.allsolutions;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
//import android.view.View;
import android.widget.Toast;
import android.media.AudioManager;
public class MyTelephonyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(true);
Bundle extras = intent.getExtras();
if (extras != null) {
String state = extras.getString(TelephonyManager.EXTRA_STATE);
Log.i("AS", "Message Received. State = " + state + ", Mode = " + audioManager.getMode());
//audioManager.setMode(AudioManager.MODE_NORMAL);
//audioManager.setSpeakerphoneOn(true);
// if (state.equals("OFFHOOK"))
// {
//audioManager.setMode(AudioManager.MODE_CURRENT);
//audioManager.setSpeakerphoneOn(true);
//audioManager.setMode(AudioManager.MODE_IN_CALL);
//audioManager.setSpeakerphoneOn(true);
//audioManager.setMode(AudioManager.MODE_RINGTONE);
//audioManager.setSpeakerphoneOn(true);
if (audioManager.isSpeakerphoneOn()) {
Log.i("AS", "Speaker on - SUCCESS.");
} else {
Log.i("AS", "Speaker could not be turned on.");
}
// }
} else {
Toast.makeText(context, "Message Received without any state", Toast.LENGTH_LONG).show();
}
}
}
Thanks.
You can set it through programmatically as below :
AudioManager audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setSpeakerphoneOn(true);
But, keep in mind that don't forgot to set speaker off when stop the call:
audioManager.setSpeakerphoneOn(false);
And, Set permission in manifest:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
This code is working fine for me.hope it will be helpful for you.
A similar question was asked and answered here.
I think the answer may be in your project's AndroidManifest.xml. Try adding:
uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"
to your manifest, which will allow your app to modify the device's audio settings.
You will also need to change your audioManager mode to MODE_IN_CALL:
audioManager.setMode(AudioManager.MODE_IN_CALL)