Sunday, June 9, 2013

Android - Make a phone call with speaker on programatically

In this post, I'm sharing with you the Android code to turn on the speaker when making a call in a programatically way .

The idea behind is to place a call and to listen to the phone state change to switch on the speaker when the call is established.

package com.danielthat.loudspeaker;

import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class Loudspeaker extends Activity {

 Button mButton;
 EditText mEdit;
 TelephonyManager manager;
 StatePhoneReceiver myPhoneStateListener;
 boolean callFromApp=false; // To control the call has been made from the application
 boolean callFromOffHook=false; // To control the change to idle state is from the app call


 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.layout_loudspeaker);

  //To be notified of changes of the phone state create an instance
  //of the TelephonyManager class and the StatePhoneReceiver class
  myPhoneStateListener = new StatePhoneReceiver(this);
  manager = ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE));

  mEdit   = (EditText)findViewById(R.id.editText1);
      
  mButton = (Button) findViewById(R.id.button1);
  mButton.setOnClickListener(new View.OnClickListener() {
  
   public void onClick(View v) {
  
    String phoneNumber = mEdit.getText().toString();
    manager.listen(myPhoneStateListener,
    PhoneStateListener.LISTEN_CALL_STATE); // start listening to the phone changes
    callFromApp=true;
    Intent i = new Intent(android.content.Intent.ACTION_CALL,
                          Uri.parse("tel:+" + phoneNumber)); // Make the call       
    startActivity(i);   
   } 
  }); 
 }


 // Monitor for changes to the state of the phone
 public class StatePhoneReceiver extends PhoneStateListener {
     Context context;
     public StatePhoneReceiver(Context context) {
         this.context = context;
     }

     @Override
     public void onCallStateChanged(int state, String incomingNumber) {
         super.onCallStateChanged(state, incomingNumber);
        
         switch (state) {
        
         case TelephonyManager.CALL_STATE_OFFHOOK: //Call is established
          if (callFromApp) {
              callFromApp=false;
              callFromOffHook=true;
                  
              try {
                Thread.sleep(500); // Delay 0,5 seconds to handle better turning on loudspeaker
              } catch (InterruptedException e) {
              }
          
              //Activate loudspeaker
              AudioManager audioManager = (AudioManager)
                                          getSystemService(Context.AUDIO_SERVICE);
              audioManager.setMode(AudioManager.MODE_IN_CALL);
              audioManager.setSpeakerphoneOn(true);
           }
           break;
        
        case TelephonyManager.CALL_STATE_IDLE: //Call is finished
          if (callFromOffHook) {
                callFromOffHook=false;
                AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                audioManager.setMode(AudioManager.MODE_NORMAL); //Deactivate loudspeaker
                manager.listen(myPhoneStateListener, // Remove listener
                      PhoneStateListener.LISTEN_NONE);
             }
          break;
         }
     }
 }
}

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.danielthat.loudspeaker"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
  
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.danielthat.loudspeaker.Loudspeaker"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".Loudspeaker" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Number to call with loudspeaker on:" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:ems="10"
        android:inputType="phone" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/editText1"
        android:layout_below="@+id/editText1"
        android:text="Call" />

</RelativeLayout>



16 comments:

  1. Excellent post. Very helpful

    ReplyDelete
    Replies
    1. 🇼🇫🇯🇪🇹🇯🇻🇳🇹🇿🇺🇿🇹🇷🇸🇷🇻🇮🇹🇱🇹🇻🇸🇪🇹🇰🇨🇭🇹🇳🇹🇹🇸🇾🇹🇲🇾🇪🇺🇬🇹🇭🇻🇪🇬🇪🏴󠁧󠁢󠁷󠁬󠁳󠁿 I lost my job few months back and there was no way to get income for my family, things was so tough and I couldn’t get anything for my children, not until a met a recommendation on a page writing how Mr Bernie Wilfred Doran helped a lady in getting a huge amount of profit every 6 working days on trading with his management on the cryptocurrency Market, to be honest I never believe it at first but I took the risk to take a loan, and I contacted him unbelievable and I was so happy I earned 15,500.00 with an investment of $1500 within 7 days of investment , the most joy is that I can now take care of my family, i am just sharing my testimony. I don’t know how to appreciate your good work Mr. Bernie Doran God will continue to bless you for being a life saver I have no way to appreciate you than to tell people about your good services. For a perfect investment and good strategies contact Mr Bernie Doran via Gmail : Berniedoransignals@gmail.com
      🇹🇼🏴󠁧󠁢󠁳󠁣󠁴󠁿🇺🇾🌔🛹🕒🏸🌤🀄️🏉𝟾🇬🇼🇬🇩🇬🇵🇮🇴🇬🇺🇭🇰🇳🇺🇰🇬🇯🇴🇯🇲🇮🇩

      Delete
  2. Hello, your code works perfectly fine. I have implemented it in different manner, as I have given a custom button on my custom screen from where user can set Speaker phone On/Off. this also works fine. but the problem is, When the User sets the Speaker Off, the Speaker sound gets normal. but the Native Speaker button still shows the Speaker On. How ca I handle it. My Code for On is,
    if(!audioManager.isSpeakerphoneOn()) {
    audioManager.setSpeakerphoneOn(true);
    }

    And for Off is:

    if(audioManager.isSpeakerphoneOn()) {
    audioManager.setSpeakerphoneOn(false);
    audioManager.setMode(AudioManager.MODE_NORMAL);
    }

    Please let me know any corrections i have to implement.

    ReplyDelete
    Replies
    1. Hi Azharuddin,

      I would say that when you are turning On the speaker you need do it as:

      if(!audioManager.isSpeakerphoneOn()) {
      audioManager.setMode(AudioManager.MODE_IN_CALL)
      audioManager.setSpeakerphoneOn(true);
      }

      If you need further support, please send the complete code of your app to support@danielthat.com and I will take a deeper look.


      Cheers,

      Daniel

      Delete
    2. Hi Daniel! Thanks for your quick reply.

      Yes, I am already setting the mode as "AudioManager.MODE_IN_CALL", as per your sample above. My Issue is, When I do setSpeakerOn(true), the loudspeaker is activated and also the default caller Loudspeaker button is highlighted (denoting the action).
      but when I call the setSpeakerOn(false), the loudspeaker is put to OFF but the default caller Loudspeaker button is still highlighted. How can I handle the default Speaker button to get Unhighlighted.

      Delete
    3. Hi again,

      Theoretically, when you set up the loudspeaker off, the default buttion should get unhighlighted as well...

      Please send me the code files and I will run it to see if I can sort out the problem.

      Send the files to support@danielthat.com

      Daniel

      Delete
    4. Ok, will send you. Please let me know If you found any Problem.

      Thanks & regards,
      Azhar

      Delete
  3. Great post! This code worked perfectly util android 5.
    Do you know how to enable speaker on Android 5 devices?
    Looks like
    audioManager.setMode(AudioManager.MODE_IN_CALL);
    audioManager.setSpeakerphoneOn(true);
    doesn't work.

    ReplyDelete
  4. I want to play audio during call can u help me???

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. public void speakerOn() {

    AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    audioManager.setMode(AudioManager.MODE_IN_CALL);
    audioManager.setSpeakerphoneOn(true);
    }

    public void speakerOff() {

    AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    audioManager.setMode(AudioManager.MODE_NORMAL);
    audioManager.setSpeakerphoneOn(false);
    }

    Not working for me. Please suggest the solution.

    ReplyDelete
  7. Hi,

    if(!audioManager.isSpeakerphoneOn()){
    audioManager.setMode(AudioManager.MODE_IN_CALL);
    audioManager.setSpeakerphoneOn(true);
    }

    is not working on API 21 and above. Please help.

    Thanks

    ReplyDelete
  8. Works perfectly.
    Thanks.

    ReplyDelete
  9. This code working well till android Oreo. after that code execute without error. but speaker did not turn on. anyone idea please share how to turn speaker on.

    ReplyDelete
  10. I have an "activity_main.xml" file (which has nothing) and a "MainActivity..java" file. Below is the complete code of "MainActiviti.java"

    package com.example.phonecall;

    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;

    import android.Manifest;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.media.AudioManager;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.Toast;

    public class MainActivity extends AppCompatActivity {
    private static final int REQUEST_CALL = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_make_call);

    makePhoneCall();
    }

    private void makePhoneCall() {
    AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    audioManager.setMode(AudioManager.MODE_NORMAL);
    audioManager.setSpeakerphoneOn(true);

    String number="1234";
    if (number.trim().length() >0) {
    if (ContextCompat.checkSelfPermission(MainActivity.this,
    Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(MainActivity.this,
    new String[] {Manifest.permission.CALL_PHONE}, REQUEST_CALL);
    } else {
    String dial ="tel:" + number;

    startActivity(new Intent(Intent.ACTION_CALL, Uri.parse(dial)));

    }
    } else {
    Toast.makeText(this, "Enter Phone Number", Toast.LENGTH_SHORT).show();
    }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int [] grantResults) {
    if (requestCode ==REQUEST_CALL) {
    if (grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED) {
    makePhoneCall();
    } else {
    Toast.makeText(this, "Pemission DENIGNED",Toast.LENGTH_SHORT).show();
    }
    }
    }
    }
    Before that I wrote in "Manifest.xml"

    /

    ReplyDelete