通过android中的服务实现sip

问题描述 投票:0回答:1

我正在开发一个Android应用程序,该应用程序应接收Sip呼叫。 sip连接应始终建立,因此我为此使用了服务。

我遇到了一些问题:

  1. sipAudioCall仅在我直接从广播接收器启动时才起作用。我需要的是将呼叫发送到服务,然后使用accept \ decline函数打开一个活动,最后打开一个活动,在该活动中应启动(并且可以结束)调用-但此操作无效。
    1. 在为注册设置sip之后,注册调用多次

P.S。我已经通过主要活动+接收器测试了sip连接,效果很好。问题始于服务+多个活动的实现

manifest.xml


      <receiver android:name=".IncomingCallReceiver" android:enabled="true" />
      <service android:name=".SipService" android:enabled="true" />
    </application>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.USE_SIP" />
    <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>  
  <uses-permission android:name="android.permission.WAKE_LOCK" />

  <uses-feature android:name="android.hardware.sip.voip" android:required="true" />
  <uses-feature android:name="android.software.sip" android:required="true" />
    <uses-feature android:name="android.hardware.wifi" android:required="true" />
    <uses-feature android:name="android.hardware.microphone" android:required="true" />

MainActivity-在这里,我检查服务是否未运行,并启动它和SIP权限。



     protected override void OnCreate(Bundle savedInstanceState)
        {
            ///stuff
            if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.UseSip) != Permission.Granted ||
                ContextCompat.CheckSelfPermission(this, Manifest.Permission.RecordAudio) != Permission.Granted ||
                ContextCompat.CheckSelfPermission(this, Manifest.Permission.ProcessOutgoingCalls) != Permission.Granted)
                ActivityCompat.RequestPermissions(this, new[] { Manifest.Permission.UseSip, Manifest.Permission.RecordAudio, Manifest.Permission.ProcessOutgoingCalls }, 0);

            StartSipService();
        }

     private void StartSipService()
       {
         if (!IsServiceRunning(typeof(SipService)))   
           StartService(new Intent(this, typeof(SipService)));             
       }

     //its deprecated ,but works for own services
     private bool IsServiceRunning(Type cls)
       {
         var manager = (ActivityManager)GetSystemService(Context.ActivityService);
         return manager.GetRunningServices(int.MaxValue).Any(service => 
                      service.Service.ClassName.Equals(Java.Lang.Class.FromType(cls).CanonicalName));
       }

SipService-它应该注册sip +绑定了呼叫接受\拒绝

public class SipService : Service, ISipRegistrationListener
    {
        public IBinder Binder { get; private set; }
        public SipManager SipManager;
        public SipProfile SipProfile;
        public IncomingCallReceiver CallReceiver;
        public SipAudioCall AudioCall;

        public override void OnCreate()
        {
            RegisterReceiver();
            CreateSipProfile("login", "pass", "domain");  
            base.OnCreate();
        }

        public void RegisterReceiver()
        {
            var filter = new IntentFilter();
            filter.AddAction("com.myapp.INCOMING_CALL");
            CallReceiver = new IncomingCallReceiver();
            RegisterReceiver(CallReceiver, filter);
        }

        public override IBinder OnBind(Intent intent)
        {
            Binder = new SipBinder(this);
            return new SipBinder(this);
        }

        public void StartCall()
        {
            if (AudioCall == null) return;
            AudioCall.AnswerCall(30);
            AudioCall.StartAudio();
            if (AudioCall.IsMuted) AudioCall.ToggleMute();
        }

        public void StopCall()
        {
            AudioCall?.Close();
        }

        public override void OnDestroy()
        {
            Binder = null;
            CloseLocalSipProfile();
            base.OnDestroy();
        }

        public void OnRegistering(string localProfileUri)  {  }

        public void OnRegistrationDone(string localProfileUri, long expiryTime) {  }

        public void OnRegistrationFailed(string localProfileUri, SipErrorCodes errorCode, string errorMessage)
        {
            CloseLocalSipProfile();
        }


        private void CreateSipProfile(string username, string password, string domain)
        {
            if (SipManager == null)
                SipManager = SipManager.NewInstance(this);
            var builder = new SipProfile.Builder(username, domain);
            builder.SetPassword(password);
            SipProfile = builder.Build();
            RegisterSipIncomСall();
        }

        private void RegisterSipIncomСall()
        {
            var intent = new Intent();
            intent.SetAction("tattelecom.nateks.INCOMING_CALL");
            var pendingIntent = PendingIntent.GetBroadcast(this, 0, intent, 
                     (PendingIntentFlags)FillInFlags.Data);
            SipManager?.Open(SipProfile, pendingIntent, null);
            SipManager?.SetRegistrationListener(SipProfile.UriString, this);           
        }

        public void CloseLocalSipProfile()
        {
            if (SipManager == null) return;
            if (SipProfile != null)
                SipManager.Close(SipProfile.UriString);
            if (CallReceiver != null)
                UnregisterReceiver(CallReceiver);
        }
    }
}

SipBinder

public class SipBinder : Binder
    {
        public SipService Service { get; private set; }
        public SipBinder(SipService service)
        {
            Service = service;
        }

        public void StartCall()
        {
            Service.StartCall();
        }

        public void StopCall()
        {
            Service.StopCall();
        }

    }

SipServiceConnection

public class SipServiceConnection : Java.Lang.Object, IServiceConnection
    {
        private CallActivity _activityCall;
        private AcceptanceActivity _activityAcceptance;
        public bool IsConnected { get; private set; }
        public SipBinder Binder { get; private set; }

        public SipServiceConnection(CallActivity activity)
        {
            _activityCall= activity;
            IsConnected = false;
            Binder = null;
        }

        public SipServiceConnection(AcceptanceActivity activity)
        {
            _activityAcceptance= activity;
            IsConnected = false;
            Binder = null;
        }


        public void OnServiceConnected(ComponentName name, IBinder service)
        {
            Binder = service as SipBinder;
            IsConnected = Binder != null;
        }

        public void OnServiceDisconnected(ComponentName name)
        {
            IsConnected = false;
            Binder = null;
        }

        public void StartCall()
        {
            if (IsConnected) Binder?.StartCall();
        }

        public void StopCall()
        {
            if (IsConnected) Binder?.StopCall();
        }

    }
}

IncomingCallReceiver-应该将呼叫发送到服务并打开接受活动

    public class IncomingCallReceiver : BroadcastReceiver
    {
         public override void OnReceive(Context context, Intent intent)
        {
            SipAudioCall incomingCall = null;

            var listener = new SipAudioCall.Listener();
            SipService service= (SipService)context;

            incomingCall = service.SipManager.TakeAudioCall(intent, listener);
            if (incomingCall.IsMuted) incomingCall.ToggleMute();
             service.AudioCall = incomingCall;

            var newIntent = new Intent(activity.ApplicationContext,typeof(AcceptanceActivity));
            newIntent.AddFlags(ActivityFlags.NewTask);
            service.StartActivity(newIntent );
}}}

AcceptanceActivity-绑定到服务,如果用户接受呼叫-打开呼叫活动。如果拒绝-service.closeCall

protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            ///stuff
            if (_serviceConnection == null)
                _serviceConnection = new SipServiceConnection(this);
            Intent serviceToStart = new Intent(this, typeof(SipService));
            BindService(serviceToStart, _serviceConnection, Bind.AutoCreate);
        }

        private void CloseOnClick(object sender, EventArgs e)
        {
            _serviceConnection?.StopCall();
            Finish();
        }

        private void AnswerOnClick(object sender, EventArgs e)
        {
            var root = new Intent(this, typeof(CallActivity));
            StartActivity(root);
            Finish();
        }

CallActivity-绑定到服务,开始音频呼叫并根据需要关闭呼叫

protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            if (_serviceConnection == null)
                _serviceConnection = new SipServiceConnection(this);
            Intent serviceToStart = new Intent(this, typeof(SipService));
            BindService(serviceToStart, _serviceConnection, Bind.AutoCreate);
            StartCall();
        }


        private void CloseOnClick(object sender, EventArgs e)
        {
            _serviceConnection?.StopCall();
        }

        private void StartCall()
        {
            _serviceConnection?.StartCall();
        }
java c# android xamarin sip
1个回答
0
投票

对于1.在启动服务时,您需要使用ForegroundService,而不是调用startService(),而是调用startForegroundService(),并在服务的onCreate中调用startForeground()

https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/foreground-services

© www.soinside.com 2019 - 2024. All rights reserved.