Нам нравится реализовывать голосовые вызовы из приложения в приложение (VoIP) с использованием форм xamarin в visual studio 2017. Здесь я нашел одно решение с использованием приложения sinch, но они дали только xamarin android github.Хотя мы пытаемся создать приложение форм xamarin с помощью Sinch, но я получаю сообщение об ошибке, когда я запускаю проект (исключение нулевого указателя) в приемнике sinchcall, мы совершенно новый голосовой вызов VoIP, мы не знаем, как вызвать (навигацию) страницу входящих вызововс Android, принять вызов, отклонить вызов и аудио-плеер.Мое требование - голосовой вызов из приложения в приложение (VoIP), после чего получите время голосового вызова, время начала и окончания.Дайте мне предложение, чтобы решить эту проблему, мы вставляем код ниже
Interface
ISinchService.cs
public interface ISinchService
{
void StartSinchClient(string username);
void StopSinchClient();
bool IsSinchClientStarted();
void CallVoice(string receipientId);
string GetUserId();
}
Interfaceimplementation
SinchService.cs
using App1.Interface;
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace App1.InterfaceImplemets
{
public class SinchService : ISinchService
{
ISinchService sinchService;// = DependencyService.Get<ISinchService>();
public SinchService()
{
sinchService = DependencyService.Get<ISinchService>();
}
public void CallVoice(string receipientId)
{
sinchService.CallVoice(receipientId);
}
public string GetUserId()
{
return sinchService.GetUserId();
}
public bool IsSinchClientStarted()
{
return sinchService.IsSinchClientStarted();
}
public void StartSinchClient(string username)
{
sinchService.StartSinchClient(username);
}
public void StopSinchClient()
{
sinchService.StopSinchClient();
}
}
}
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:App1"
x:Class="App1.MainPage">
<StackLayout VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand">
<Label x:Name="progress"
Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Label Text="Enter user name"
TextColor="Purple"
FontSize="Medium"/>
<Entry x:Name="usernameId"
Placeholder="enter username here"
PlaceholderColor="MediumAquamarine"
TextColor="Purple"
FontSize="Medium"/>
<Button x:Name="loginBtn"
Text="Login"
TextColor="White"
BackgroundColor="Purple"
Clicked="loginBtn_Clicked"/>
</StackLayout>
</ContentPage>
MainPage.xaml.cs
using App1.InterfaceImplemets;
using App1.View;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App1
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
SinchService sinchService;
public MainPage()
{
InitializeComponent();
sinchService = new SinchService();
}
private async void loginBtn_Clicked(object sender, EventArgs e)
{
string userId = usernameId.Text;
if (userId != null)
{
sinchService.StartSinchClient(userId);
while (!IsSinchStarted())
{
progress.Text = "Please wait app is starting to sinch service...";
await Task.Delay(500);
}
Debug.WriteLine(sinchService.IsSinchClientStarted().ToString());
LaunchReciepientAsync();
}
}
private void LaunchReciepientAsync()
{
Navigation.PushModalAsync(new RecipientPage(sinchService));
}
private bool IsSinchStarted()
{
return sinchService.IsSinchClientStarted();
}
}
}
RecipientPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App1.View.RecipientPage">
<ContentPage.Content>
<StackLayout>
<Label x:Name="userId"
Text="Welcome to Xamarin Forms!" />
<Label Text="Enter reciepient username"
TextColor="Purple"
FontSize="Medium"/>
<Entry x:Name="reciepientId"
Placeholder="enter username here"
PlaceholderColor="MediumAquamarine"
TextColor="Purple"
FontSize="Medium"/>
<Button x:Name="voiceCallBtn"
Text="Voice"
TextColor="White"
BackgroundColor="Purple"
Clicked="voiceCallBtn_Clicked"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
RecipientPage.xaml.cs
using App1.InterfaceImplemets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App1.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RecipientPage : ContentPage
{
SinchService sinchService;
public RecipientPage()
{
InitializeComponent();
}
public RecipientPage(SinchService sinchService)
{
InitializeComponent();
this.sinchService = sinchService;
userId.Text = sinchService.GetUserId();
}
private void voiceCallBtn_Clicked(object sender, EventArgs e)
{
if (!string.IsNullOrWhiteSpace(reciepientId.Text))
{
LaunchVoiceAsync();
}
}
private void LaunchVoiceAsync()
{
sinchService.CallVoice(reciepientId.Text);
Navigation.PushModalAsync(new CallPage(sinchService, reciepientId.Text, voiceCallBtn.Text));
}
}
}
CallPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App1.View.CallPage">
<ContentPage.Content>
<StackLayout>
<Label Text="Welcome to Xamarin Forms!" />
<Label x:Name="reciepientId"
Text=""
TextColor="Purple"
FontSize="Medium"/>
<Label x:Name="callState"
Text=""
TextColor="Purple"
FontSize="Medium"/>
<Label x:Name="callDuration"
Text="0:00"
TextColor="Purple"
FontSize="Medium"/>
<Button x:Name="stopBtn"
Text="STOP"
TextColor="White"
BackgroundColor="Red"/>
<Button x:Name="voiceCallBtn"
Text="Voice"
TextColor="White"
BackgroundColor="Purple"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
CallPage.xaml.cs
using App1.InterfaceImplemets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App1.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CallPage : ContentPage
{
private SinchService sinchService;
private string text1;
private string text2;
public CallPage()
{
InitializeComponent();
}
public CallPage(SinchService sinchService, string text1, string text2)
{
this.sinchService = sinchService;
this.text1 = text1;
this.text2 = text2;
}
}
}
Android
InterfaceImplementations
SinchService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using App1.Droid.InterfaceImplementations;
using App1.Interface;
using Com.Sinch.Android.Rtc;
using Com.Sinch.Android.Rtc.Calling;
using Xamarin.Forms;
[assembly: Xamarin.Forms.Dependency(typeof(SinchService))]
namespace App1.Droid.InterfaceImplementations
{
[Service]
public class SinchService : Service, ISinchService
{
// go to link and signup(https://portal.sinch.com/#/signup) then you will get sinch app key and app secret key and call id
static readonly string APP_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
static readonly string APP_SECRET = "xxxxxxxxxxxxxxxxxxxx";
static readonly string ENVIRONMENT = "clientapi.sinch.com";
public static readonly string CALL_ID = "xxxxxx";
static readonly string TAG = nameof(SinchService);
public SinchServiceInterface mSinchServiceInterface;
ISinchClient mSinchClient;
string mUserId;
IStartFailedListener mListener;
public SinchService()
{
mSinchServiceInterface = new SinchServiceInterface(this);
}
public void CallVoice(string receipientId)
{
mSinchServiceInterface.CallUserVoice(receipientId);
}
public override IBinder OnBind(Intent intent)
{
return mSinchServiceInterface;
}
public override void OnCreate()
{
base.OnCreate();
}
public override void OnDestroy()
{
if (mSinchClient != null && mSinchClient.IsStarted)
{
mSinchClient.Terminate();
}
base.OnDestroy();
}
public void StartSinchClient(string username)
{
if (mSinchClient == null)
{
mUserId = username;
mSinchClient = Sinch.SinchClientBuilder.Context(Forms.Context).UserId(username)
.ApplicationKey(APP_KEY)
.ApplicationSecret(APP_SECRET)
.EnvironmentHost(ENVIRONMENT).Build();
mSinchClient.SetSupportCalling(true);
mSinchClient.SetSupportMessaging(true);
mSinchClient.SetSupportPushNotifications(true);
//mSinchClient.SetSupportManagedPush(true);
mSinchClient.SetSupportActiveConnectionInBackground(true);
mSinchClient.StartListeningOnActiveConnection();
mSinchClient.AddSinchClientListener(new SinchClientListener(this));
// Permission READ_PHONE_STATE is needed to respect native calls.
mSinchClient.CallClient.SetRespectNativeCalls(false);
mSinchClient.CallClient.AddCallClientListener(new SinchCallClientListener(this));
// mSinchClient.MessageClient.AddMessageClientListener(new SinchMessageClientListener(this));
mSinchClient.Start();
Log.Debug(TAG, "Started1!!!!!!!!!!!!!!!!!!!!!11");
}
}
public void StopSinchClient()
{
if (mSinchClient != null)
{
mSinchClient.Terminate();
mSinchClient = null;
}
}
public bool IsSinchClientStarted()
{
return (mSinchClient != null && mSinchClient.IsStarted);
}
public string GetUserId()
{
return mUserId;
}
public interface IStartFailedListener
{
void OnStartFailed(ISinchError error);
void OnStarted();
}
public class SinchServiceInterface : Binder
{
private SinchService sinchService;
public SinchServiceInterface(SinchService sinchService)
{
this.sinchService = sinchService;
}
public ICall CallPhoneNumber(String phoneNumber)
{
return sinchService.mSinchClient.CallClient.CallPhoneNumber(phoneNumber);
}
public ICall CallUserVoice(String userId)
{
if (sinchService.mSinchClient == null)
{
return null;
}
return sinchService.mSinchClient.CallClient.CallUser(userId);
}
public string GetUserName()
{
return sinchService.mUserId;
}
public bool IsStarted()
{
return sinchService.IsSinchClientStarted();
}
public void StartClient(String userName)
{
sinchService.StartSinchClient(userName);
}
public void StopClient()
{
sinchService.StopSinchClient();
}
public void SetStartListener(IStartFailedListener listener)
{
sinchService.mListener = listener;
}
public ICall GetCall(String callId)
{
return sinchService.mSinchClient.CallClient.GetCall(callId);
}
}
class SinchCallClientListener : Java.Lang.Object, ICallClientListener
{
readonly SinchService sinchService;
public SinchCallClientListener(SinchService sinchService)
{
this.sinchService = sinchService;
}
public void OnIncomingCall(ICallClient callClient, ICall call)
{
Log.Debug(TAG, "Incoming call");
//Here i am getting error null pointer exception while i run the project
Intent intent = new Intent(sinchService, typeof(IncomingCallScreenActivity));
intent.PutExtra(CALL_ID, call.CallId);
intent.AddFlags(ActivityFlags.NewTask);
sinchService.StartActivity(intent);
}
}
class SinchClientListener : Java.Lang.Object, ISinchClientListener
{
private readonly SinchService sinchService;
public SinchClientListener(SinchService sinchService)
{
this.sinchService = sinchService;
}
public void OnClientFailed(ISinchClient sinchClient, ISinchError sinchError)
{
if (sinchService.mListener != null)
{
sinchService.mListener.OnStartFailed(sinchError);
}
sinchService.mSinchClient.Terminate();
sinchService.mSinchClient = null;
}
public void OnClientStarted(ISinchClient sinchClient)
{
Log.Debug(TAG, "SinchClient started");
if (sinchService.mListener != null)
{
sinchService.mListener.OnStarted();
}
}
public void OnClientStopped(ISinchClient sinchClient)
{
Log.Debug(TAG, "SinchClient stopped");
}
public void OnLogMessage(int level, string area, string message)
{
switch (level)
{
case 3://Log.DEBUG:
Log.Debug(area, message);
break;
case 6://Log.ERROR:
Log.Error(area, message);
break;
case 4://Log.INFO:
Log.Info(area, message);
break;
case 2://Log.VERBOSE:
Log.Verbose(area, message);
break;
case 5://Log.WARN:
Log.Warn(area, message);
break;
}
}
public void OnRegistrationCredentialsRequired(ISinchClient sinchClient, IClientRegistration clientReg)
{
//throw new NotImplementedException();
}
}
}
}
//Here i created a activity class
//Activity
//IncomingCallScreenActivity.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace App1.Droid
{
[Activity(Label = "IncomingCallScreenActivity")]
public class IncomingCallScreenActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Create your application here
}
}
}
Note: We use to develop app using this link(https://github.com/Onotseike/CallMessageDemoSinch)