I'm setting up AudioManager with bluetooth to record an audio , the code is already there but not working and whenever i check for AudioManager.EXTRA_SCO_AUDIO_STATE , it never connects and returns -1 , i do not know why , can anyone please guide me to solve this issue , Thank you .
This is my receiver
public class CallReceiver extends BroadcastReceiver {
public CallReceiver() {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle;
String state;
String incomingNumber;
String action = intent.getAction();
int BLE = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1); // always return -1
if (BLE == AudioManager.SCO_AUDIO_STATE_CONNECTED){ // never connected
// start bluetooth headset
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE)
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
}
}
}
Receiver in Manifest File
<receiver
android:name=".recorder.CallReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.media.extra.SCO_AUDIO_STATE"/>
<action
android:name="android.media.ACTION_SCO_AUDIO_STATE_UPDATED"/>
</intent-filter>
</receiver>
Before checking the current state, first need to find the action, I check for AudioManager.EXTRA_SCO_AUDIO_STATE, it never connects and returns -1. After finding the current state, If found 'SCO_AUDIO_STATE_CONNECTED' setBluetoothScoOn and startBluetoothSco.
#Override public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equalsIgnoreCase(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED))
{
int currentState = context . getIntExtra (AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
Log.d("Bluetooth Connect - ", "Audio SCO: " + AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
switch(currentState) {
case AudioManager.SCO_AUDIO_STATE_CONNECTED :
{
Log.i("Bluetooth Connect", "SCO_AUDIO_STATE_CONNECTED");
AudioManager audioManager =(AudioManager) context . getSystemService (Context.AUDIO_SERVICE)
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
}
break;
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED :
{
Log.e("Bluetooth disconnect", "SCO_AUDIO_STATE_DISCONNECTED");
}
break;
default: Log.e("Bluetooth unknown - ", "unknown state received:"+l_state);
}
} else Log.e("Bluetooth Connect - ", "onReceive:action=" + action);
}
Related
I will make a new Android application. How to to auto-start it as soon as the mobile is plugged into charging?
If this is successfully done, then the application will be opened automatically when the charger is plugged to the mobile phone.
You need a broadcast receiver for this.
Add this to your manifest:
<receiver android:name=".PowerConnectionReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
</receiver>
Now add this to your class
public class PowerConnectionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
status == BatteryManager.BATTERY_STATUS_FULL;
int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
boolean usbCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
boolean acCharging = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
if (isCharging) {
Intent i = new Intent();
i.setClassName("com.className", "com.classname.YourActivityClass");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i)
}
}
}
Don't forget to replace things like com.className with yours.
I'm working on application which shows list of certain connected bluetooth low energy devices, so user can choose which one of them he wants to configure.
The problem is that you can't just list all connected devices. As far as I know there are three possible ways:
Use BluetoothProfiles
bluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
This fails because android won't connect to GATT server, when device connects, so device is neither under GATT_SERVER nor GATT profile. However once I call connectGatt method,
bluetoothDevice.connectGatt(getApplicationContext(), false, gattCallback);
device can be found under both GATT_SERVER and GATT profile. Other profiles are not supported by low energy devices.
List paired devices and try connectGatt on each of them
List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
for(BluetoothDevice device : bluetoothAdapter.getBondedDevices()) {
BluetoothGatt gatt = device.connectGatt(getApplicationContext(), false, gattCallback);
if(gatt != null) {
connectedDevices.add(device);
}
gatt.disconnect();
}
This method cannot be used as it cannot determine if device is already connected or only in range but not connected
On system boot start service listening to ACL_CONNECTED and ACL_DISCONNECTED intents and maintaining list of connected devices
Manifest
<service android:name=".ManagerService" android:enabled="true" />
<receiver
android:name=".BootFinishedReceiver"
android:directBootAware="true"
android:enabled="true"
android:exported="false"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Receiver
public class BootFinishedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, ManagerService.class);
context.startService(serviceIntent);
}
}
Service
public class ManagerService extends Service {
private static List<BluetoothDevice> connectedDevices;
#Override
public void onCreate() {
connectedDevices = new ArrayList<BluetoothDevice>();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
registerReceiver(connectionReceiver, filter);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
unregisterReceiver(connectionReceiver);
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private final BroadcastReceiver connectionReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
connectedDevices.add(device);
}else{
connectedDevices.remove(device);
}
}
};
public static List<BluetoothDevice> getConnectedDevices() {
return connectedDevices;
}
}
Since 3.1 apps can no longer receive system intents before activity is started, so this cannot be used either.
Is there any other way or how can I achieve it now in later android versions?
Thanks for any suggestions
Well, I found out that you can still use ON_BOOT_COMPLETED, but you have to allow it in setting on your device. So my problem is solved
I know that i can detect new outgoing call by this receiver :
<receiver android:name=".NewOutgoingCallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
And in OnReceive method i want to know which sim making this call ?
public class NewOutgoingCallReceiver extends BroadcastReceiver
{
#Override
public void onReceive( Context context, Intent intent )
{
// here i want to check which sim is making that new call
}
}
The intent received by your broadcast receiver should have some extra information in the bundle, one of which is the 'slot' - meaning the SIM slot.
You can get this in your example above like this - this is for API 22 and above:
public class NewOutgoingCallReceiver extends BroadcastReceiver
{
#Override
public void onReceive( Context context, Intent intent )
{
//check which sim is making that new call
String callSlot = "";
Bundle bundle = intent.getExtras();
callSlot =String.valueOf(bundle.getInt("slot", -1));
if(callSlot == "0"){
//Call is from SIM slot0
} else if(callSlot =="1"){
//Call is from SIM slot 1
}
}
}
I think this will be more correct
val SIM_SLOT_NAMES = arrayOf(
"extra_asus_dial_use_dualsim",
"com.android.phone.extra.slot",
"slot",
"simslot",
"sim_slot",
"subscription",
"Subscription",
"phone",
"com.android.phone.DialingMode",
"simSlot",
"slot_id",
"simId",
"simnum",
"phone_type",
"slotId",
"slotIdx"
)
private fun getSimSlot(extras: Bundle?): Int {
for (name in SIM_SLOT_NAMES) {
if (extras?.containsKey(name) == true) {
return extras.getInt(name, 0)
}
}
return 0
}
// usage
getSimSlot(intent.extras)
How could start app or activity when headphone or headset connected to mobile it's possible ? i read some example in another site about broadcast receiver.i'm new in android developing thanks if write example.
private class MusicIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
Toast.makeText(MainActivity.this, "unplug", Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(MainActivity.this, "plug", Toast.LENGTH_SHORT).show();
break;
default:
}
}
public class MusicIntentReceiver extends WakefulBroadcastReceiver {
public void onReceive(Context ctx, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
Toast.makeText(ctx, "unplug", Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(ctx, "plug", Toast.LENGTH_SHORT).show();
break;
}
}
}
}
but this code work when application is running.
try this permission to your manifest file.
<receiver
android:name="AudioJackReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.HEADSET_PLUG" />
</intent-filter>
</receiver>
I am trying to display toast after receiving an call, I have implemented all necessary things needed to register broadcast receiver but it is not displaying toast. I am trying to run this program on Marshmallow device
MyCallReceiver.java -
package com.suhas.callreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
public class MyCallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
// This code will execute when the phone has an incoming call
// get the phone number
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context, "Call from:" +incomingNumber, Toast.LENGTH_LONG).show();
Log.d("MyTrack call", "call receive");
} else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_IDLE))
{
Toast.makeText(context, "Detected call hangup event", Toast.LENGTH_LONG).show();
}
else if (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(
TelephonyManager.EXTRA_STATE_OFFHOOK)) {
// This code will execute when the call is disconnected
}
}
}
AndroidManifest.xml -
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.suhas.msgmanager">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:allowBackup="true"
android:icon="#mipmap/msgis"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
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>
<activity android:name="com.example.suhas.msgmanager.MyDialog" android:launchMode="singleTask"
android:theme="#android:style/Theme.Translucent" />
<service android:name="com.example.suhas.msgmanager.ChatHeadService"></service>
<receiver android:name=".MyCallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<activity android:name=".AddMessageActivity">
</activity>
</application>
</manifest>
I have one MainActivity with one default label saying Hello World.
In Case of Marshmallow Version, We have a concept called Runtime permission which is to be made inside Activity in order to work with the permission.
Runtime permission provides a way to ask user for particular permission at runtime while he runs activity for first time.
This are two things you have to specify :
//specify any constant number for permission
public final static int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 11;
// Specify following bit of code in OnCreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}
}
}
//specify this method which will popup window asking user for permission at runtime
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_PHONE_STATE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
}
return;
}
}
}
this will provide a way to work with Marshmallow devices
You have given wrong package name in the receiver.
You should define receiver as below:
<receiver android:name="com.suhas.callreceiver.MyCallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
In target API 23 or higher as per the Marshmallow the applications needs run time permission or manual in your device setting>> apps>> select your app>> permission
this link can help you
I successfully implemented in our App. Get the reference from here.
Call Receive Method
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//Log.w("intent " , intent.getAction().toString());
TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
MyPhoneStateListener customPhoneListener = new MyPhoneStateListener();
telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
Bundle bundle = intent.getExtras();
String phone_number = bundle.getString("incoming_number");
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
// String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
state = TelephonyManager.CALL_STATE_RINGING;
}
if (phone_number == null || "".equals(phone_number)) {
return;
}
customPhoneListener.onCallStateChanged(context, state, phone_number);
Toast.makeText(context, "Phone Number " + phone_number , Toast.LENGTH_SHORT).show();
}}
Listener Method
public class MyPhoneStateListener extends PhoneStateListener {
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
public void onCallStateChanged(Context context, int state, String phoneNumber){
if(lastState == state){
//No change, debounce extras
return;
}
System.out.println("Number inside onCallStateChange : " + phoneNumber);
switch(state){
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
Toast.makeText(context, "Incoming Call Ringing " + phoneNumber, Toast.LENGTH_SHORT).show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
Toast.makeText(context, "Outgoing Call Started " + phoneNumber, Toast.LENGTH_SHORT).show();
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
//Ring but no pickup- a miss
Toast.makeText(context, "Ringing but no pickup" + phoneNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
else if(isIncoming){
Toast.makeText(context, "Incoming " + phoneNumber + " Call time " + callStartTime , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(context, "outgoing " + phoneNumber + " Call time " + callStartTime +" Date " + new Date() , Toast.LENGTH_SHORT).show();
}
break;
}
lastState = state;
}} }
Get the reference for full solution