Apparently there has been a new thing i wasn’t aware of, and that is call popups. What this essentially does is it prompts you to answer/mute/decline the call without never leaving the current app you are focused on. Of course, since the app doesn’t lose focus Unity doesn’t mute it. Does anyone have a possible workaround for this?
Experienced the same issue. There’s a setting on device under Settings
→ Call
→ Call-related pop-ups
called Call notification pop-ups
which can be toggled to test this.
I wrote a native extension to get the phone call status of the device. This can be extended to mute your application during a call.
Java code
package com.your.app.package;
import android.content.Context;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.unity3d.player.UnityPlayerActivity;
import com.unity3d.player.UnityPlayer;
public class CallStatusBridge extends UnityPlayerActivity
{
private static int currentState = 0;
private static String gameObject = "callstate";
private static String callBackName = "OnCallStateChange";
protected void onCreate(Bundle savedInstanceState)
{
Log.d("Unity", "CallStatus created");
super.onCreate(savedInstanceState);
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener phoneStateListener = new PhoneStateListener()
{
@Override
public void onCallStateChanged(int state, String incomingNumber)
{
switch (state)
{
case TelephonyManager.CALL_STATE_IDLE:
currentState = 0;
break;
case TelephonyManager.CALL_STATE_RINGING:
currentState = 1;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
currentState = 2;
break;
default:
currentState = 0;
break;
}
Log.d("Unity", "CurrentState:" + currentState);
sendCallStateToUnity(currentState);
}
};
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
public static int getCallStatus()
{
return currentState;
}
public static void setCallBack(String gameObject, String callBackName)
{
Log.d("Unity", "setCallBack");
CallStatusBridge.gameObject = gameObject;
CallStatusBridge.callBackName = callBackName;
}
public static void sendCallStateToUnity(int state){
Log.d("Unity", "sendCallState");
UnityPlayer.UnitySendMessage(gameObject, callBackName, "" + state);
}
}
C# code
using UnityEngine;
using System.Collections;
public class CallStateBridge : MonoBehaviour {
#if UNITY_ANDROID
AndroidJavaObject jc;
#endif
void Start ()
{
#if UNITY_ANDROID
AndroidJNI.AttachCurrentThread();
jc = new AndroidJavaClass("com.ea.android.theimpossibleline.rowsamsung.CallStatusBridge");
jc.CallStatic("setCallBack", new object[2] {gameObject.name, "OnCallStateChange"});
#endif
}
public void OnCallStateChange(string state){
Debug.Log("call status:" + state);
}
#if UNITY_ANDROID
public int CheckCallStatus(){
return jc.CallStatic<int>("getCallStatus");
}
#endif
}
Add this to your Android Manifest in Unity
<!-- CallStatusBridge -->
<activity android:name=".CallStatusBridge"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
I ended up implementing a very similar solution to yours, but not having a bridge, just extending the unity activity and doing everything on the native side.
public class UnityPlayerNativeActivity extends NativeActivity
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
private Boolean wasPlaying;
// Setup activity layout
@Override protected void onCreate (Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
getWindow().takeSurface(null);
getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy
mUnityPlayer = new UnityPlayer(this);
if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))
getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
wasPlaying=true;
TelephonyManager mgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
mgr.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
PhoneStateListener mPhoneStateListener = new PhoneStateListener()
{
@Override
public void onCallStateChanged(int state, String incomingNumber)
{
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if( state == TelephonyManager.CALL_STATE_RINGING )
{
if(wasPlaying){
am.setStreamMute(AudioManager.STREAM_MUSIC, true);
wasPlaying=false;
}
}
else if(state == TelephonyManager.CALL_STATE_IDLE )
{ // Not in call: Play music
if(wasPlaying==false){
am.setStreamMute(AudioManager.STREAM_MUSIC, false);
wasPlaying=true;
}
}
else if( state == TelephonyManager.CALL_STATE_OFFHOOK )
{
if(wasPlaying==true){
am.setStreamMute(AudioManager.STREAM_MUSIC, true);
wasPlaying=false;
}
}
super.onCallStateChanged(state, incomingNumber);
}
};
Try using “OnApplicationPause(bool PauseState)” based on the PauseStateboolean value try decreasing/increasing or switching off audio listener or making audio source mute.
Hope this may help you.