많은 사람들처럼 저도 asmack과 Openfire를 사용하여 채팅 응용 프로그램을 작성하고 있습니다. 여전히 기본적인 것은 아니지만, Spark를 사용하여 로그인 한 사용자와 에뮬레이터를 사용하여 메시지를 보내고받습니다.서비스가 묶여 있는지 확인
일부 읽기 후에 나는 모든 활동에 바인딩하는 XMPP 연결을위한 서비스를 만들기로 결정했습니다. 현재 3 가지 활동이 있습니다.
- MainActivity (사용자 로그인 및 XMPP 연결).
- RosterActivity
- ChatActivity
내 질문은 두 가지이다 (리스트 뷰는 사용자의 연락처를 포함) :
이 서비스에 대한 모든 활동을 결합 할 필요가있다, 또는 그것이 가능할 것이다 그냥 MainActivity를 바인딩하고 XMPPConnection을 추가로 전달 하시겠습니까? 그렇다면 통과는 어떻게 할 수 있습니까?
로그인하고 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>
답장을 보내 주셔서 감사합니다. 정말 유용하지만, 최종 프로젝트이므로 모든 것을 명시 적으로 처리해야합니다. – countzero