我在 android 中使用 native sip 创建了 sip 应用程序。在其中我在从 sip 服务器注销帐户时遇到问题,每次我都收到 DATA_CONNECTION_LOST 。我也在 android 文档中看到,但是那里没有对此错误的简要解释。此外,它还面临着各种错误,而 regiterin 如 in_progress、transaction_terminated 等在 doc 中没有适当的解释。 这是我的代码:
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.*;
import android.widget.Chronometer;
import android.net.sip.*;
import java.text.ParseException;
import commonUtilities.Prefs;
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public String sipAddress = null;
public SipManager manager = null;
public SipProfile me = null;
public SipAudioCall call = null;
public SipErrorCode sipcode;
public SipException sipexeception;
public static WalkieTalkieActivity walkiy;
public static WalkieTalkieActivity getInstance(Context c) {
if (walkiy == null) {
walkiy = new WalkieTalkieActivity();
}
return walkiy;
}@
Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// "Push to talk" can be a serious pain when the screen keeps turning off.
// Let's prevent that.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Log.e("onCreate", "onCreate");
initializeManager(this);
}@
Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager(this);
}@
Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
}@
Override
protected void onResume() {
// TODO Auto-generated method stub
initializeManager(this);
super.onResume();
}
public void initializeManager(Context ctx) {
if (manager == null) {
Log.e("initialising ", "ini manager");
manager = SipManager.newInstance(ctx);
}
initializeLocalProfile(ctx);
}
public void initializeLocalProfile(final Context ctx) {
if (manager == null) {
updateStatus("Not Supporting.", ctx);
Log.e("return", "manager is null ");
return;
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
String username = prefs.getString("namePref", Prefs.getUserName(ctx));
String domain = prefs.getString("domainPref", "255.235.472");
String password = prefs.getString("passPref", Prefs.getUserPassword(ctx));
if (username.length() == 0 || domain.length() == 0 || password.length() == 0) {
return;
}
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
me = builder.build();
Intent intent = new Intent();
intent.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctx, 0, intent, Intent.FILL_IN_DATA);
manager.open(me, pendingIntent, null);
if (!manager.isRegistered(me.getUriString())) {
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
Log.e("Sip restration", "Registering with SIP Server...");
updateStatus("Registering with SIP Server...", ctx);
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
Log.e("Sip restration", "Ready");
updateStatus("Ready", ctx);
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
Log.e("Registration Error Code ", SipErrorCode.toString(errorCode) + errorCode);
updateStatus(errorCode + " " + SipErrorCode.toString(errorCode), ctx);
}
});
} else {
Log.e("already register", "already register");
updateStatus("Ready", ctx);
}
} catch (ParseException pe) {
updateStatus("Connection Error.", ctx);
} catch (SipException se) {
updateStatus("Connection error.", ctx);
}
}
public Boolean closeLocalProfile() {
Log.e("Closing profile", "closing profile " + me.getUriString());
if (manager == null) {
return false;
}
try {
if (me != null) {
Log.e("Unregistering profile", "Un registering profile ");
manager.unregister(me, null);
manager.close(me.getUriString());
}
} catch (Exception ee) {
Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
}
return false;
}
public void initiateCall(String number, final Context ctx, final View v) {
// updateStatus(sipAddress);
Log.d("Number", "" + number);
sipAddress = number;
Log.e("initiating call", "initiating call");
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {@
Override
public void onCallBusy(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("buzy", "buzy");
super.onCallBusy(call);
}@
Override
public void onCallHeld(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("held", "held");
super.onCallHeld(call);
}@
Override
public void onCalling(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("calling", "calling");
super.onCalling(call);
}@
Override
public void onChanged(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("changed", "changed");
super.onChanged(call);
}@
Override
public void onError(SipAudioCall call, int errorCode,
String errorMessage) {
// TODO Auto-generated method stub
Log.e("call error", "error" + SipErrorCode.toString(errorCode));
CallingScreen.fa.finish();
super.onError(call, errorCode, errorMessage);
}@
Override
public void onReadyToCall(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("ready to call", "ready to call ");
super.onReadyToCall(call);
}@
Override
public void onRinging(SipAudioCall call, SipProfile caller) {
// TODO Auto-generated method stub
Log.e("ringing", "ringing");
super.onRinging(call, caller);
}@
Override
public void onRingingBack(SipAudioCall call) {
// TODO Auto-generated method stub
Log.e("ringing back", "ringing back");
super.onRingingBack(call);
}@
Override
public void onCallEstablished(SipAudioCall call) {
Log.e("call established", "call established");
call.startAudio();
updateTime(true, ctx);
}@
Override
public void onCallEnded(SipAudioCall call) {
Log.e("call ended", "call ended");
updateTime(false, ctx);
CallingScreen.fa.finish();
}
};
Log.e("param 1 ", "" + me.getUriString());
call = manager.makeAudioCall(me.getUriString(), sipAddress + "@216.245.200.2:5060", listener, 30);
} catch (Exception e) {
e.printStackTrace();
Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
closeLocalProfile();
} catch (Exception ee) {
ee.printStackTrace();
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
public void updateStatus(final String status, final Context context) {
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
generateNotification(context, status);
}
});
}
public void updateTime(final Boolean status, final Context context) {
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
if (status) {
CallingScreen.fa.ch = (Chronometer) CallingScreen.fa.findViewById(R.id.time);
CallingScreen.fa.ch.setTypeface(CallingScreen.normal);
CallingScreen.fa.calling_screen_text.setVisibility(View.GONE);
CallingScreen.fa.ch.setVisibility(View.VISIBLE);
CallingScreen.fa.ch.start();
} else {
CallingScreen.fa.ch.stop();
}
}
});
}
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if (useName == null) {
useName = call.getPeerProfile().getUserName();
}
// updateStatus(useName + "@" + call.getPeerProfile().getSipDomain());
}
public boolean onTouch(View v, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
public void endcall() {
if (call != null) {
try {
call.endCall();
} catch (SipException se) {
Log.d("WalkieTalkieActivity/onOptionsItemSelected",
"Error ending call.", se);
}
call.close();
}
}
public void speaker(Boolean speak) {
if (call != null)
call.setSpeakerMode(speak);
}
public static void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager)
context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, message, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, Splash_screen.class);
// set intent so it does not start a new activity
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent =
PendingIntent.getActivity(context, 0, notificationIntent, 0);
notification.setLatestEventInfo(context, title, message, intent);
notificationManager.notify(0, notification);
}
public Boolean isRegistered() {
if (manager != null && me != null)
try {
return manager.isRegistered(me.getUriString());
} catch (SipException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
LOGCAT1
12 - 23 14: 19: 10.930: E / Unregistering profile(32139): Un registering profile
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): Failed to close local profile.
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): android.net.sip.SipException: SipService.createSession() returns null
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.net.sip.SipManager.unregister(SipManager.java: 507)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.phone91.android.WalkieTalkieActivity.closeLocalProfile(WalkieTalkieActivity.java: 144)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.phone91.android.DialerActivity$1$2.onClick(DialerActivity.java: 79)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java: 174)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.os.Handler.dispatchMessage(Handler.java: 99)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.os.Looper.loop(Looper.java: 155)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at android.app.ActivityThread.main(ActivityThread.java: 5520)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at java.lang.reflect.Method.invokeNative(Native Method)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at java.lang.reflect.Method.invoke(Method.java: 511)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 1029)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 796)
12 - 23 14: 19: 10.990: D / WalkieTalkieActivity / onDestroy(32139): at dalvik.system.NativeStart.main(Native Method)
日志 CAT2:
12-23 14:53:28.890: E/Unregistering profile(2001): Un registering profile
12-23 14:53:30.050: E/Registration Error Code(2001): DATA_CONNECTION_LOST-10
最佳答案
我一直在检查 SipDemo 示例代码,我假设您将其用作您的应用程序的引用,也遇到了这个错误,但有注册过程。
在检查了 Android 的源代码 (4.1) 之后,我发现这是堆栈实现中的一个错误。更详细:
setRegistrationListener)时,由于网络信息尚未更新(未收到任何 Intent ),它会返回 SipErrorCode.DATA_CONNECTION_LOST,但实际上, session 最终已正确注册。 在您的情况下,当您在 unregister 方法中提供 SipRegistrationListener 时,此过程失败。一个丑陋的解决方法是等待一段时间以接收 Intent 或不提供监听器。
你还会看到,如果你用 setRegistrationLister 替换 unregister 调用,你仍然会收到同样的错误,所以你也可以尝试创建一个高层管理,这是,在 onRegistrationDone 回调中,您可以设置一个标志以了解您是否可以关闭配置文件。像这样的东西:
public void updateStatus(final int status, final Context context) {
if(status == STATUS_OK)
registered = true;
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
generateNotification(context, statusToString(status));
}
});
}
并且,在关闭本地配置文件时:
public Boolean closeLocalProfile() {
Log.e("Closing profile", "closing profile " + me.getUriString());
if (manager == null || !registered) {
return false;
}
try {
if (me != null) {
Log.e("Unregistering profile", "Un registering profile ");
manager.unregister(me, null);
manager.close(me.getUriString());
}
} catch (Exception ee) {
Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
}
return false;
}
请注意,我在 updateStatus 中使用了整数而不是字符串,并使用了辅助函数 statusToString 将状态代码转换为字符串。
正如您可能注意到的那样,这将添加一个额外的管理层,最初,它应该已经在堆栈中,但事实并非如此。我不太确定这是否会修复所有返回错误(在检查源代码后我看到了几个可能的错误),但应该有所帮助。
关于android - SIP:错误 DATA_CONNECTION_LOST,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20676709/
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa
“输出”是一个序列化的OpenStruct。定义标题try(:output).try(:data).try(:title)结束什么会更好?:) 最佳答案 或者只是这样:deftitleoutput.data.titlerescuenilend 关于ruby-on-rails-更好的替代方法try(:output).try(:data).try(:name)?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.c
这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]