2013-03-06 72 views
0

我想寫一個簡單的SIP客戶端在Android上運行,我下載了SIPDemo項目,以便與它聯繫,然後我開始寫我的代碼,我遇到了一些問題。SIP手動註冊+ Textview更新

讓我們告訴你的代碼:

package com.example.gt_sipclient; 

import java.text.ParseException; 

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.os.Handler; 
import android.os.Message; 
import android.preference.PreferenceManager; 
import android.app.Activity; 
import android.app.PendingIntent; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.WindowManager; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.TextView; 

//Activity android simple pour effectuer quelques appels VoIP 
//et réaliser des tests. 
public class SIPCliMainActivity extends Activity { 

private TextView numText, domText, usrText, pswText, callerIDText, sipText, 
     statusText; 
private EditText numInput, domInput, usrInput, pswInput, callerIDInput, 
     sipInput; 
private Button callBtn, registerBtn, unregisterBtn; 
private String number, domain, username, password, callerID, sipPort; 

public SipManager mySipManager = null; 
public SipProfile mySipProfile = null; 
public SipAudioCall call = null; 
public IncomingCallReceiver callReceiver; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_sipcli_main); 

    // TODO: virer les éléments qui ne seront pas utilisés au final 
    // Get the layout elements 
    // TextViews 
    numText = (TextView) findViewById(R.id.number_title); 
    domText = (TextView) findViewById(R.id.domain); 
    usrText = (TextView) findViewById(R.id.username); 
    pswText = (TextView) findViewById(R.id.password); 
    callerIDText = (TextView) findViewById(R.id.callerid); 
    sipText = (TextView) findViewById(R.id.sipport); 
    statusText = (TextView) findViewById(R.id.status); 

    // EditText views 
    numInput = (EditText) findViewById(R.id.number_input); 
    domInput = (EditText) findViewById(R.id.domain_input); 
    usrInput = (EditText) findViewById(R.id.username_input); 
    pswInput = (EditText) findViewById(R.id.password_input); 
    callerIDInput = (EditText) findViewById(R.id.callerid_input); 
    sipInput = (EditText) findViewById(R.id.sipport_input); 

    // Button views 
    callBtn = (Button) findViewById(R.id.callbtn); 
    registerBtn = (Button) findViewById(R.id.registerbtn); 
    unregisterBtn = (Button) findViewById(R.id.unregisterbtn); 

    // make sure that the screen will not turn off during the app lifecycle 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

} 

// handle click events without implementing listeners (see layout file 
// android:onclick) 
// register handling 
public void registerClick(View v) { 

    // Get the SIP account parameters 
    domain = domInput.getText().toString().trim(); 
    username = usrInput.getText().toString().trim(); 

    // TODO: penser à stocker le psw en MD5 et à le faire aussi dans le 
    // sip.conf 
    password = pswInput.getText().toString().trim(); 
    callerID = callerIDInput.getText().toString().trim(); 
    sipPort = sipInput.getText().toString().trim(); 

    sipManagerInit(); 

} 

public void unregisterClick(View v) { 

    myProfileClose(); 

} 

// TODO: call handling 
public void callClick(View v) { 

} 

public void sipManagerInit() { 
    if (mySipManager == null) 
     mySipManager = SipManager.newInstance(this); 

    myProfileInit(); 
} 

public void myProfileInit() { 
    if (mySipManager == null) 
     return; 

    // TODO: test si un profil est déjà présent 

    // TODO: Load persistent data if they exist 
    // SharedPreferences myPreferences = 
    // PreferenceManager.getDefaultSharedPreferences(getBaseContext()); 

    if (username == null || password == null || domain == null) { 
     updateStatus("Please fill the form."); 
     return; 
    } 

    try { 
     SipProfile.Builder builder = new SipProfile.Builder(username, 
       domain); 
     builder.setPassword(password); 
     // important 
     //builder.setAutoRegistration(false); 
     mySipProfile = builder.build(); 

     // open myProfile for making and receiving calls 

     Intent i = new Intent(); 
     i.setAction("com.example.gt_sipclient.INCOMING_CALL"); 
     PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 
       Intent.FILL_IN_DATA); 
     mySipManager.open(mySipProfile, pi, null); 

     //manual register 
     //mySipManager.register(mySipProfile, 60, null); 

     // set SIP registration events 

     mySipManager.setRegistrationListener(mySipProfile.getUriString(), 
       new SipRegistrationListener() { 

        @Override 
        public void onRegistrationFailed(String arg0, int arg1, 
          String arg2) { 
         updateStatus("Registration failed"); 

        } 

        @Override 
        public void onRegistrationDone(String arg0, long arg1) { 
         updateStatus("Registration OK"); 
         registerBtn.setVisibility(View.INVISIBLE); 
        } 

        @Override 
        public void onRegistering(String arg0) { 
         updateStatus("Registering with SIP server..."); 

        } 
       }); 

    } catch (ParseException e) { 
     // TODO getMessage juste pour le debug 
     updateStatus("Connection error." + e.getMessage()); 
    } catch (SipException e) { 
     // TODO getMessage juste pour le debug 
     updateStatus("Connection error SIP." + e.getMessage()); 
    } 

} 

public void myProfileClose() { 
    if (mySipManager == null) 
     return; 

    try { 
     if (mySipProfile != null) { 
      mySipManager.close(mySipProfile.getUriString()); 
      unregisterBtn.setVisibility(View.VISIBLE); 
     } 
    } catch (Exception ee) { 
     Log.d("WalkieTalkieActivity/onDestroy", 
       "Failed to close local profile.", ee); 
    } 
} 

//TODO: completer cette methode pour se desinscrire du serveur manuellement 
public void myProfileUnregister(){ 
    if(mySipManager == null) 
     return; 

    try { 
     if(mySipProfile != null && mySipManager.isRegistered(mySipProfile.getUriString())){ 
      mySipManager.unregister(mySipProfile, new SipRegistrationListener(){ 

       @Override 
       public void onRegistering(String localProfileUri) { 
        // TODO Auto-generated method stub 

       } 

       @Override 
       public void onRegistrationDone(String localProfileUri, 
         long expiryTime) { 
        // TODO Auto-generated method stub 

       } 

       @Override 
       public void onRegistrationFailed(String localProfileUri, 
         int errorCode, String errorMessage) { 
        // TODO Auto-generated method stub 

       } 

      }); 
     } 
    } catch (SipException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    // Inflate the menu; this adds items to the action bar if it is present. 
    getMenuInflater().inflate(R.menu.sipcli_main, menu); 
    return true; 
} 

//Allez on va coder un thread propre pour la maj 
public void updateStatus(final String status) { 


    this.runOnUiThread(new Runnable() { 

     @Override 
     public void run() { 
      statusText.setText(status); 

     } 

    }); 

} 

public void updateStatus(SipAudioCall call) { 
    String useName = call.getPeerProfile().getDisplayName(); 
    // TODO: watch it 
    if (useName == null) 
     useName = call.getPeerProfile().getUserName(); 

    updateStatus(useName + "@" + call.getPeerProfile().getSipDomain()); 

} 

    } 

好了,現在當我運行的應用程序,我有這些錯誤:

03-06 17:38:35.931: E/JavaBinder(3754): *** Uncaught remote exception! (Exceptions are not yet supported across processes.) 
03-06 17:38:35.931: E/JavaBinder(3754): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4039) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.view.ViewRootImpl.invalidateChild(ViewRootImpl.java:722) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:771) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.view.ViewGroup.invalidateChild(ViewGroup.java:4005) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.view.View.invalidate(View.java:8581) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.view.View.setFlags(View.java:6766) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.view.View.setVisibility(View.java:4617) 
03-06 17:38:35.931: E/JavaBinder(3754):  at com.example.gt_sipclient.SIPCliMainActivity$1.onRegistrationDone(SIPCliMainActivity.java:163) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.net.sip.SipManager$ListenerRelay.onRegistrationDone(SipManager.java:601) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.net.sip.ISipSessionListener$Stub.onTransact(ISipSessionListener.java:167) 
03-06 17:38:35.931: E/JavaBinder(3754):  at android.os.Binder.execTransact(Binder.java:338) 
03-06 17:38:35.931: E/JavaBinder(3754):  at dalvik.system.NativeStart.run(Native Method) 

的事情是,我試圖更新爲每個註冊步驟通過一個TextView,我認爲這將是可以使用runOnUiThread但我顯然缺少的東西。不要擔心註冊,它運行良好(這有點慢,但無論如何...),我可以看到我的SIP服務器上的設備。

我的第二個問題是關於避免自動註冊:我希望用戶通過點擊一個按鈕(如zoiper客戶端,如果你知道的話)註冊/取消自己註冊到SIP服務器我找不到任何這方面的例子,但如果你有一些我會很樂意閱讀這些。 如果您需要更多信息,請告訴我。

回答

0

您還需要將registerBtn.setVisibility(View.INVISIBLE);移動到runOnUiThread之內。更改onRegistrationDone代碼爲:

@Override 
public void onRegistrationDone(String arg0, long arg1) { 
    updateStatus("Registration OK"); 
    } 
///..your code here.... 

public void updateStatus(final String status) { 
    SIPCliMainActivity.this.runOnUiThread(new Runnable() { 

     @Override 
     public void run() { 
      statusText.setText(status); 
      registerBtn.setVisibility(View.INVISIBLE); 
     } 

    }); 
} 
+0

謝謝,我忘了這一個!又一個愚蠢的錯誤。 – onizukaek 2013-03-06 20:28:58

+0

是的,它是一個巨大的錯誤! 無論如何,我決定暫時不要設置我的registerbtn,因爲如果我使用這種方法設置它,每次註冊步驟完成後都會設置按鈕。 關於我關於SipManager.register的第二個問題的任何提示? – onizukaek 2013-03-07 07:53:21