2013-03-07 2 views
0

많은 사람들처럼 저도 asmack과 Openfire를 사용하여 채팅 응용 프로그램을 작성하고 있습니다. 여전히 기본적인 것은 아니지만, Spark를 사용하여 로그인 한 사용자와 에뮬레이터를 사용하여 메시지를 보내고받습니다.서비스가 묶여 있는지 확인

일부 읽기 후에 나는 모든 활동에 바인딩하는 XMPP 연결을위한 서비스를 만들기로 결정했습니다. 현재 3 가지 활동이 있습니다.

  • MainActivity (사용자 로그인 및 XMPP 연결).
  • RosterActivity
  • ChatActivity

내 질문은 두 가지이다 (리스트 뷰는 사용자의 연락처를 포함) :

  1. 이 서비스에 대한 모든 활동을 결합 할 필요가있다, 또는 그것이 가능할 것이다 그냥 MainActivity를 바인딩하고 XMPPConnection을 추가로 전달 하시겠습니까? 그렇다면 통과는 어떻게 할 수 있습니까?

  2. 로그인하고 RosterActivity를 시작한 후 onCreate() 메소드에서 서비스를 바인딩합니다. onStart 메서드에서 mBound 변수를 확인하면 항상 false입니다. SystemClock.sleep()을 시도해 보았습니다. 제대로 작동하는지 알 수 없었습니다. 실제로 나를 괴롭히는 것은 내가 처음에이 활동을 썼을 때, 클릭했을 때 목록을 채우는 절차를 시작하는 버튼을 사용했습니다. 그것은 완벽하게 작동했습니다.

    그래서 내가 무엇을 놓치고 있습니까? 분명히 사용자가 연락처를보기 위해 단추를 눌러야하는 것은 원하지 않습니다. 목록을 onStart()에 채우고 싶습니다. 왜 서비스가 onClickListener 내부에서 접근하려고 할 때 바인드 되는가? 그리고 왜 단순히 onStart에서 작동하지 않는가?

    비동기 바인딩과 관련이 있다고 생각합니다.하지만 정확히 무엇을 찾으려고합니다.

MainActivity :

package com.example.smack_text; 

import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.EditText; 
import android.widget.Toast; 

public class MainActivity extends Activity 
{ 
XMPPService mService; 
boolean mBound = false; 
Button logBtn; 
Button disBtn; 
EditText userTxt; 
EditText passTxt; 

@Override 
protected void onCreate(Bundle savedInstanceState) 
{ 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
//  BIND SERVICE 
Intent intent = new Intent(getApplicationContext(), XMPPService.class); 
bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
} 

@Override 
protected void onStart() 
{ 
super.onStart(); 

userTxt = (EditText) findViewById(R.id.userTxt); 
passTxt = (EditText) findViewById(R.id.passTxt); 

logBtn = (Button) findViewById(R.id.logBtn); 
disBtn = (Button) findViewById(R.id.disBtn); 
logBtn.setOnClickListener(new OnClickListener() 
    { 

    @Override 
    public void onClick(View v) 
     { 
     final String user = new String(userTxt.getText().toString()); 
     final String pass = new String(passTxt.getText().toString()); 

     if(user=="" || pass=="") 
      { 
      Toast.makeText(getApplicationContext(), "Enter name and pass",   
Toast.LENGTH_LONG).show(); 
      } 
     if(mBound) 
     { 
       mService.connect(user,pass); 
       Log.d("Alex","connected"); 
     } 
     else 
     { 
      Log.d("Alex","error in connecting"); 
     } 
     Intent roster = new Intent(); 
     roster.setClass(getApplicationContext(), RosterActivity.class); 
     startActivity(roster); 
    } 
}); 

disBtn.setOnClickListener(new OnClickListener() 
{ 
@Override 
public void onClick(View v) 
    { 
    if(mBound) 
     { 
     mService.disconnect(); 
     Log.d("Alex","disconnected"); 
     } 
    else 
     { 
     Log.d("Alex","error in disconnecting"); 
     } 
    } 
}); 


} 

@Override 
protected void onDestroy() 
{ 
// Unbind from the service 
if (mBound) 
    { 
    unbindService(mConnection); 
    mBound = false; 
    } 
super.onDestroy(); 
} 

private ServiceConnection mConnection = new ServiceConnection() 
{ 
@Override 
public void onServiceConnected(ComponentName name, IBinder service) 
    { 
    mService = ((XMPPService.LocalBinder)service).getService(); 
    mBound = true; 
    } 

@Override 
public void onServiceDisconnected(ComponentName name) 
    { 
    mBound = false; 
    } 
}; 
} 

RosterActivity :

package com.example.smack_text; 

import java.util.Collection; 
import org.jivesoftware.smack.Roster; 
import org.jivesoftware.smack.RosterEntry; 
import org.jivesoftware.smack.packet.Presence; 
import android.app.AlertDialog; 
import android.app.ListActivity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.SystemClock; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.ListView; 
import android.widget.Toast; 

public class RosterActivity extends ListActivity{ 

boolean mBound = false; 
XMPPService mService; 
Button btn; 


@Override 
public void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.roster); 

    Intent intent = new Intent(getApplicationContext(), XMPPService.class); 
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
    } 

@Override 
public void onStart(){ 
    super.onStart(); 
//  btn = (Button) findViewById(R.id.button1); 
//  btn.setOnClickListener(new OnClickListener() { 

//   @Override 
//   public void onClick(View v) { 

      if(mBound){ 
       Log.d("Alex","roster connected"); 

       Roster roster = mService.connection.getRoster(); 
//     XWRIS TO RELOAD DN DOULEYEI 
       roster.reload(); 

       Integer length = roster.getEntryCount(); 
       String[] users = new String[length]; 
       String[] userPresence = new String[length]; 

       Integer i=0; 

       Collection<RosterEntry> entries = roster.getEntries(); 

       for(RosterEntry entry:entries){ 
        users[i] = entry.getName(); 


Presence tmpPres = roster.getPresence(entry.getUser()); 
        userPresence[i] = tmpPres.toString(); 
        Log.d("RosterActivity" , entry.getUser().toString()); 

        i++; 

       } 


ArrayAdapter<String> adapter = new ArrayAdapter<String> (RosterActivity.this, 

android.R.layout.simple_expandable_list_item_1,  users); 
        setListAdapter(adapter); 



      } 
      else{ 

Toast.makeText(getApplicationContext(), "service not bound yet", Toast.LENGTH_LONG).show(); 
      } 

     } 
//  }); 
// } 

@Override 
protected void onDestroy() { 

    // Unbind from the service 
    if (mBound) { 
     unbindService(mConnection); 
     mBound = false; 
    } 
    super.onDestroy(); 
} 

@Override 
protected void onListItemClick(ListView l, View v, int position, long id) { 


    // Creating the dialog 
    AlertDialog.Builder builder = new AlertDialog.Builder(this); 

    Object o = l.getItemAtPosition(position); 
    String str = o.toString(); 
    Log.d("Roster Activity",str); 

    builder.setTitle("Start Chat?"); 
    builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { 

     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      Intent chat = new Intent(); 
      chat.setClass(getApplicationContext(), ChatActivity.class); 
      startActivity(chat); 
     } 
    }); 


    AlertDialog alert = builder.create(); 
    alert.show(); 
} 




private ServiceConnection mConnection = new ServiceConnection() { 


    @Override 
    public void onServiceConnected(ComponentName name, IBinder service) { 
     mService = ((XMPPService.LocalBinder)service).getService(); 

     mBound = true; 

    } 

    @Override 
    public void onServiceDisconnected(ComponentName name) { 
     mBound = false; 

    } 
    }; 

} 

XMPPService :

package com.example.smack_text; 

import java.io.File; 

import org.jivesoftware.smack.ConnectionConfiguration; 
import org.jivesoftware.smack.XMPPConnection; 
import org.jivesoftware.smack.XMPPException; 

import android.app.Service; 
import android.content.Intent; 
import android.os.Binder; 
import android.os.Build; 
import android.os.IBinder; 
import android.util.Log; 
import android.widget.Toast; 

public class XMPPService extends Service{ 

XMPPConnection connection; 
private final IBinder mBinder = new LocalBinder(); 


    @Override 
    public void onCreate(){ 
     super.onCreate(); 
    } 

    /** 
    * Class used for the client Binder. Because we know this service always 
    * runs in the same process as its clients, we don't need to deal with IPC. 
    */ 
    public class LocalBinder extends Binder { 
     XMPPService getService() { 
      return XMPPService.this; 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return mBinder; 
    } 

    public void connect(final String user, final String pass) { 


     Log.d("Xmpp Alex","in service"); 


     ConnectionConfiguration config = new ConnectionConfiguration("10.0.2.2",5222); 

//   KEYSTORE SETTINGS 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 
      config.setTruststoreType("AndroidCAStore"); 
      config.setTruststorePassword(null); 
      config.setTruststorePath(null); 
     } else { 
      config.setTruststoreType("BKS"); 
      String path = System.getProperty("javax.net.ssl.trustStore"); 
      if (path == null) 
       path = System.getProperty("java.home") + File.separator + "etc" 
        + File.separator + "security" + File.separator 
        + "cacerts.bks"; 
      config.setTruststorePath(path); 
     } 

//   Create XMPP Connection 

     connection = new XMPPConnection(config); 

//   THELEI TO RUNNABLE ALLIWS DN TREXEI 

     new Thread(new Runnable() { 
      @Override 
      public void run() { 

       try { 
        connection.connect(); 
        connection.login(user, pass); 
        if(connection.isConnected()){ 
         Log.d("Alex", "connected biatch!"); 
//       try { 
//        Thread.sleep(5000); 
//       } catch (InterruptedException e) { 
//        e.printStackTrace(); 
//       } 
        } 
        else{ 
         Log.d("Alex","not connected"); 
        } 


       } catch (XMPPException e) { 
        e.printStackTrace(); 
       } 
      } 
     }).start(); 


    } 

    public void disconnect(){ 
     if(connection.isConnected()){ 
      connection.disconnect(); 
     } 

else{Toast.makeText(getApplicationContext(), "not  connected",Toast.LENGTH_LONG).show(); 
     } 
    } 

} 

그리고 레이아웃 :

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="#000000" 
tools:context=".MainActivity" > 

<EditText 
    android:id="@+id/userTxt" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentLeft="true" 
    android:layout_below="@+id/textView1" 
    android:layout_marginLeft="30dp" 
    android:layout_marginTop="27dp" 
    android:background="#FFFFFF" 
    android:ems="10" 
    android:inputType="textPersonName" > 

    <requestFocus /> 
</EditText> 

<TextView 
    android:id="@+id/textView1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignLeft="@+id/userTxt" 
    android:layout_alignParentTop="true" 
    android:layout_marginLeft="14dp" 
    android:layout_marginTop="52dp" 
    android:background="#FFFFFF" 
    android:text="User Name :" /> 

<TextView 
    android:id="@+id/textView2" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignLeft="@+id/textView1" 
    android:layout_below="@+id/userTxt" 
    android:layout_marginTop="62dp" 
    android:background="#FFFFFF" 
    android:text="Password :" /> 

<EditText 
    android:id="@+id/passTxt" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignLeft="@+id/userTxt" 
    android:layout_below="@+id/textView2" 
    android:layout_marginTop="58dp" 
    android:background="#FFFFFF" 
    android:ems="10" 
    android:inputType="textPassword" /> 

<Button 
    android:id="@+id/logBtn" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignRight="@+id/textView2" 
    android:layout_below="@+id/passTxt" 
    android:layout_marginTop="66dp" 
    android:background="#FFFFFF" 
    android:text="Log In" /> 

<Button 
    android:id="@+id/disBtn" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignBottom="@+id/logBtn" 
    android:layout_alignRight="@+id/userTxt" 
    android:background="#FFFFFF" 
    android:text="disconnect" /> 

</RelativeLayout> 

roster.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:orientation="vertical" > 

<Button 
    android:id="@+id/button1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Button" /> 

<ListView 
    android:id="@android:id/list" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" > 
</ListView> 

</LinearLayout> 

답변

0

난 항상 이런 상황이 조금 혼란 스러울 수 있다고 생각, 그래서 나는 Vapor API에이 간단한을 만들기위한 지원을 썼다 - 설계된 안드로이드 프레임 워크를 응용 프로그램을 쉽게 dev에 만들 수 있습니다.

모든 바인딩을 암시 적으로 관리하며 서비스 클래스별로 바인딩을 검색 할 수도 있습니다 (코드에서 연결 개체를 유지 관리 할 필요가 없습니다.).당신은 당신이 이런 식으로 원하는 것을 할 수있는 그것을 밖으로 시도하고 싶었다면

(VaporActivity 사용 VaporServiceBindable) : 사실에 기초 분명히 당신이 설명하는 문제의 종류의 단순화 된 골격의

public class RosterActivity extends VaporActivity{ 

    public void create(VaporBundle bundle){ 

     $.srv(XMPPService.class); // optionally, first start the service 

     // set up the callback for when the service is bound 
     $.hook(SERVICE_BIND).hookIn(new $$hookee(){ 

      public void call(String hookName, VaporBundle args){ 

      // put your code here that depends on the binding... 

      } 

     }); 

     // bind to the service 
     $.bind(XMPPService.class); 


    } 

} 

, 바인딩은 비동기입니다. 이 자동으로 생성 된 그 ServiceConnection 이전을 검색 후드 아래

this.service(XMPPService.class).foo(); // some method in the service 

: 당신이 다음 활동 안에 당신의 서비스에서 방법을 사용하려는 경우 당신은 어디서든 쉽게 그렇게 할 수있는, 더 무엇

서비스에 대한 IBinder에 대한 액세스 권한을 제공합니다.

관심이 있으시면 VaporService을 확인하시기 바랍니다. 임의적으로 일시 중지, 잠자기 및 재시작 할 수있는 자체 스레드 내에서 서비스를 실행하므로 자세한 내용을 염려하지 않고 서비스를 완벽하게 제어 할 수 있습니다.

희망이 있습니다.

+0

답장을 보내 주셔서 감사합니다. 정말 유용하지만, 최종 프로젝트이므로 모든 것을 명시 적으로 처리해야합니다. – countzero

관련 문제