Ich entwickle SIP-Client für Android und habe ein Problem. Das Problem ist, dass ich kein Audio habe, während zwei Clients verbunden sind. Der Server, den ich verwende, ist www.minisipserver.com. Die Methode onCallEstablished vom SipAudioCall.Listener wird jedes Mal aufgerufen.Android SIP Call etabliert, aber kein Audio
Dies ist die Klasse, die BroadcastReceiver erweitert, der auf den Anruf wartet. `
package uk.co.tbw.sip.calling;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.sip.SipAudioCall;
import android.net.sip.SipException;
import android.net.sip.SipProfile;
import uk.co.tbw.utils.TBWLogger;
public class IncomingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
Call callActivity = (Call) context;
SipAudioCall.Listener listener = new myListener(context);
incomingCall = callActivity.mManager.takeAudioCall(intent, listener);
incomingCall.startAudio();
callActivity.mAudioCall = incomingCall;
callActivity.updateStatus(incomingCall);
} catch (SipException e) {
if (incomingCall != null) {
incomingCall.close();
e.printStackTrace();
}
}
}
class myListener extends SipAudioCall.Listener {
private Context context;
public myListener(Context context) {
this.context = context;
}
@Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (SipException e) {
e.printStackTrace();
}
}
@Override
public void onReadyToCall(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onReadyToCall : " + call.toString());
}
@Override
public void onCalling(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onCalling : " + call.toString());
}
@Override
public void onRingingBack(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onRingingBack : " + call.toString());
}
@Override
public void onCallEstablished(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onCallEstablished : " + call.toString());
if (call.isInCall()) {
TBWLogger.d("IncomingCallReceiver.java isInCall : " + call.toString());
}
if (call.isOnHold()) {
TBWLogger.d("IncomingCallReceiver.java isOnHold : " + call.toString());
}
if (call.isMuted()) {
TBWLogger.d("IncomingCallReceiver.java isMuted : " + call.toString());
}
call.startAudio();
}
@Override
public void onCallEnded(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onCallEnded : " + call.toString());
}
@Override
public void onCallBusy(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onCallBusy : " + call.toString());
}
@Override
public void onCallHeld(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onCallHeld : " + call.toString());
}
@Override
public void onError(SipAudioCall call, int errorCode, String errorMessage) {
TBWLogger.d("IncomingCallReceiver.java IncomingCallReceiver.java onError : " + call.toString() + "; errorCode: " + errorCode + "; errorMessage: " + errorMessage);
}
@Override
public void onChanged(SipAudioCall call) {
TBWLogger.d("IncomingCallReceiver.java onReadyToCall : " + call.toString());
}
}
}
`
Call.java Aktivität
package uk.co.tbw.sip.calling;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.sip.SipAudioCall;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
import android.net.sip.SipRegistrationListener;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.c77.androidstreamingclient.lib.rtp.RtpMediaDecoder;
import java.text.ParseException;
import uk.co.tbw.R;
import uk.co.tbw.utils.TBWLogger;
public class Call extends AppCompatActivity {
public static final int REQUEST_PERMISSION_CODE = 1567;
public String mSipAddress = null;
public SipManager mManager = null;
public SipProfile mProfile = null;
public SipAudioCall mAudioCall = null;
public IncomingCallReceiver mCallReceiver;
private static final int CALL_ADDRESS = 1;
private static final int SET_AUTH_INFO = 2;
private static final int UPDATE_SETTINGS_DIALOG = 3;
private static final int HANG_UP = 4;
private RtpMediaDecoder rtpMediaDecoder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Button callBtn = (Button) findViewById(R.id.answer_btn);
Button closeBtn = (Button) findViewById(R.id.close_btn);
SurfaceView view = new SurfaceView(this);
rtpMediaDecoder = new RtpMediaDecoder(view);
rtpMediaDecoder.start();
callBtn.setOnClickListener(v -> {
EditText textField = (EditText) findViewById(R.id.userToCallEditText);
mSipAddress = textField.getText().toString();
initiateCall();
});
closeBtn.setOnClickListener(v -> {
if (mAudioCall != null) {
try {
mAudioCall.endCall();
TBWLogger.d("Call.java endCall");
} catch (SipException e) {
Log.d("WalkieTalkieActivity/onOptionsItemSelected",
"Error ending call.", e);
}
mAudioCall.close();
}
});
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
mCallReceiver = new IncomingCallReceiver();
this.registerReceiver(mCallReceiver, filter);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
@Override
protected void onStart() {
super.onStart();
initializeManager();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mAudioCall != null) {
mAudioCall.close();
}
closeLocalProfile();
if (mCallReceiver != null) {
this.unregisterReceiver(mCallReceiver);
}
rtpMediaDecoder.release();
}
@Override
protected void onStop() {
rtpMediaDecoder.release();
super.onStop();
}
private void closeLocalProfile() {
if (mManager == null) {
return;
}
try {
if (mProfile != null) {
mManager.close(mProfile.getUriString());
}
} catch (SipException e) {
Log.d("CallActivity/onDestroy", "Failed to close local profile.", e);
}
}
private void initializeManager() {
TBWLogger.d("initializeManager()");
if (mManager == null) {
mManager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
private void initializeLocalProfile() {
TBWLogger.d("initializeLocalProfile");
if (mManager == null) {
return;
}
if (mProfile != null) {
closeLocalProfile();
}
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
String username = preferences.getString("namePref", "");
String domain = preferences.getString("domainPref", "");
String password = preferences.getString("passPref", "");
if (username.length() == 0 || domain.length() == 0 || password.length() == 0) { //|| password.length() == 0
showDialog(UPDATE_SETTINGS_DIALOG);
return;
}
try {
TBWLogger.d("Building new sipProfile");
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mProfile = builder.build();
Intent intent = new Intent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, Intent.FILL_IN_DATA);
mManager.open(mProfile, pendingIntent, new SipRegistrationListener() {
@Override
public void onRegistering(String localProfileUri) {
TBWLogger.d("onRegistering");
updateStatus("Registering with SIP Server...");
}
@Override
public void onRegistrationDone(String localProfileUri, long expiryTime) {
TBWLogger.d("onRegistrationDone");
updateStatus("Ready");
}
@Override
public void onRegistrationFailed(String localProfileUri, int errorCode, String errorMessage) {
TBWLogger.d("onRegistrationFailed:" + " errorMessage:" + errorMessage + " errorCode:" + errorCode
+ " localProfile:" + localProfileUri);
updateStatus("Registration failed. Please check settings.");
}
});
} catch (ParseException e) {
updateStatus("Connection Error.");
e.printStackTrace();
} catch (SipException e) {
updateStatus("Connection Error.");
e.printStackTrace();
}
}
public void initiateCall() {
updateStatus(mSipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
@Override
public void onReadyToCall(SipAudioCall call) {
TBWLogger.d("Call.java onReadyToCall: " + call);
}
@Override
public void onRingingBack(SipAudioCall call) {
TBWLogger.d("Call.java onRingingBack: " + call);
}
@Override
public void onCallBusy(SipAudioCall call) {
TBWLogger.d("Call.java onCallBusy: " + call);
}
@Override
public void onCallHeld(SipAudioCall call) {
TBWLogger.d("Call.java onCallHeld: " + call);
}
@Override
public void onChanged(SipAudioCall call) {
TBWLogger.d("Call.java onChanged: " + call);
}
@Override
public void onCallEstablished(SipAudioCall call) {
// AudioManager audio = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
// audio.setMode(AudioManager.MODE_IN_COMMUNICATION);
// AudioGroup audioGroup = new AudioGroup();
// audioGroup.setMode(AudioGroup.MODE_NORMAL);
// AudioStream audioStream = null;
// try {
// audioStream = new AudioStream(InetAddress.getByAddress(IncomingCallReceiver.getLocalIPAddress()));
// } catch (SocketException e) {
// e.printStackTrace();
// } catch (UnknownHostException e) {
// e.printStackTrace();
// }
// audioStream.setCodec(AudioCodec.PCMU);
// audioStream.setMode(RtpStream.MODE_NORMAL);
// //set receiver(vlc player) machine ip address(please update with your machine ip)
// try {
// audioStream.associate(InetAddress.getByAddress(new byte[] {(byte)192, (byte)168, (byte)1, (byte)19 }), 22222);
// } catch (UnknownHostException e) {
// e.printStackTrace();
// }
// audioStream.join(audioGroup);
//call.setSpeakerMode(true);
call.startAudio();
// if (call.isMuted()) {
// call.toggleMute();
// }
updateStatus(call);
mAudioCall.startAudio();
//mAudioCall.setSpeakerMode(true);
TBWLogger.d("Call.java onCallEstablished(): ");
}
@Override
public void onRinging(SipAudioCall call, SipProfile caller) {
Toast.makeText(Call.this, "Calling", Toast.LENGTH_LONG).show();
try {
call.answerCall(30);
} catch (SipException e) {
e.printStackTrace();
}
TBWLogger.d("Call.java onRinging(): ");
}
@Override
public void onCalling(SipAudioCall call) {
Toast.makeText(Call.this, "Calling", Toast.LENGTH_LONG).show();
TBWLogger.d("Call.java onRinging(): ");
}
@Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready");
TBWLogger.d("Call.java onCallEnded(): ");
}
@Override
public void onError(SipAudioCall call, int errorCode, String errorMessage) {
TBWLogger.d("Call.java onError: errorCode: " + errorCode + "; errorMessage: " + errorMessage);
updateStatus("Call.java onError: errorCode: " + errorCode + "; errorMessage: " + errorMessage);
}
};
mAudioCall = mManager.makeAudioCall(mProfile.getUriString(), mSipAddress, listener, 30);
} catch (SipException e) {
Log.i("InitiateCall", "Error when trying to close manager", e);
if (mProfile != null) {
try {
mManager.close(mProfile.getUriString());
} catch (SipException e1) {
Log.i("InitiateCall", "Error when trying to close manager", e1);
e1.printStackTrace();
}
}
if (mAudioCall != null) {
mAudioCall.close();
}
}
}
public void updateStatus(String s) {
this.runOnUiThread(() -> {
TextView label = (TextView) findViewById(R.id.label);
label.setText(s);
});
}
public void updateStatus(SipAudioCall s) {
String userName = s.getPeerProfile().getDisplayName();
if (userName == null) {
userName = s.getPeerProfile().getUserName();
}
updateStatus(userName + "@" + s.getPeerProfile().getSipDomain());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, SET_AUTH_INFO, 0, "Edit your SIP Info");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case SET_AUTH_INFO:
updatePreferences();
break;
}
return true;
}
//TODO: check the break statements
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case CALL_ADDRESS:
LayoutInflater factory = LayoutInflater.from(this);
final View textBoxView = factory.inflate(R.layout.call_address_dialog, null);
return new AlertDialog.Builder(this)
.setTitle("Call Someone")
.setView(textBoxView)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
EditText textField = (EditText) (textBoxView.findViewById(R.id.call_address_edit));
mSipAddress = textField.getText().toString();
initiateCall();
}
})
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).create();
case UPDATE_SETTINGS_DIALOG:
return new AlertDialog.Builder(this)
.setMessage("Please update your SIP Account Settings.")
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
updatePreferences();
}
})
.setNegativeButton(
android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// Noop.
}
})
.create();
}
return null;
}
private void updatePreferences() {
Intent settingsActivity = new Intent(getBaseContext(), SipSetting.class);
startActivity(settingsActivity);
}
}
`
Manifest`
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CONFIGURE_SIP" />
<uses-permission android:name="android.software.sip" android:required="true" />
<uses-permission android:name="android.software.sip.voip" android:required="true" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CONFIGURE_SIP" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.hardware.wifi" android:required="true"/>
<uses-permission android:name="android.software.sip.voip" android:required="true" />
<uses-permission android:name="android.hardware.microphone" android:required="true"/>
<uses-permission android:name="android.hardware.sip.voip" android:required="true" />
<uses-permission android:name="android.hardware.telephony" android:required="false" />
<application ...
<receiver android:name=".sip.calling.IncomingCallReceiver" android:label="Call Receiver"/>
<activity
android:name=".sip.calling.Call"
android:configChanges="orientation|keyboardHidden"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="uk.co.tbw.MainActivity"/>
</activity>
</application>
`
Ich verwende https://developer.android.com/guide/topics/connectivity/sip.html – emchoko