2

サーバーで新しいユーザーを作成する際に問題に直面していejabberdますが、サインインは正常に機能しています。新しいユーザーを登録し、2 人以上のユーザー間でチャットするために、github リポジトリ ( https://github.com/dilicode/LetsChat ) を使用しました。私はインターネットで検索し、それらを登録するいくつかの方法を見つけました: 1.add

%% In-band registration
{access, register, [{allow, all}]}.

サーバーのアクセスルールでejabberd、2.も追加します

{mod_register, [
      {access_from, register},
       ...
                ] ...

ejabberdサーバーのアクセスルールでそれ。私のサインアップ活動は次のとおりです。

public class SignupActivity extends AppCompatActivity implements OnClickListener, Listener<Boolean> {
    private static final int REQUEST_CODE_SELECT_PICTURE = 1;
    private static final int REQUEST_CODE_CROP_IMAGE = 2;

    private static final String RAW_PHOTO_FILE_NAME = "camera.png";
    private static final String AVATAR_FILE_NAME = "avatar.png";

    private EditText nameText;
    private EditText phoneNumberText;
    private EditText passwordText;

    private Button submitButton;
    private ImageButton uploadAvatarButton;

    private File rawImageFile;
    private File avatarImageFile;

    private SignupTask signupTask;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_signup);

        nameText = (EditText)findViewById(R.id.et_name);
        phoneNumberText = (EditText)findViewById(R.id.et_phone_number);
        passwordText = (EditText)findViewById(R.id.et_password);
        uploadAvatarButton = (ImageButton)findViewById(R.id.btn_upload_avatar);
        submitButton = (Button)findViewById(R.id.btn_submit);

        submitButton.setOnClickListener(this);
        uploadAvatarButton.setOnClickListener(this);

        File dir = FileUtils.getDiskCacheDir(this, "temp");
        if (!dir.exists()) {
            dir.mkdirs();
        }
        rawImageFile = new File(dir, RAW_PHOTO_FILE_NAME);
        avatarImageFile = new File(dir, AVATAR_FILE_NAME);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onClick(View v) {
        if (v == submitButton) {
            String phoneNumber = phoneNumberText.getText().toString();
            String password = passwordText.getText().toString();
            String name = nameText.getText().toString();

            if (phoneNumber.trim().length() == 0 || password.trim().length() == 0 ||
                    name.trim().length() == 0) {
                Toast.makeText(this, R.string.incomplete_signup_info, Toast.LENGTH_SHORT).show();
                return;
            }

            signupTask = new SignupTask(this, this, phoneNumber, password, name, getAvatarBytes());
            signupTask.execute();
        } else if(v == uploadAvatarButton) {
            chooseAction();
        }
    }

    private void chooseAction() {
        Intent captureImageIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(rawImageFile));

        Intent pickIntent = new Intent(Intent.ACTION_GET_CONTENT);
        pickIntent.setType("image/*");

        Intent chooserIntent = Intent.createChooser(pickIntent, getString(R.string.profile_photo));
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {captureImageIntent});

        startActivityForResult(chooserIntent, REQUEST_CODE_SELECT_PICTURE);
    }

    @Override
    public void onResponse(Boolean result) {
        if (result) {
            Toast.makeText(this, R.string.login_success, Toast.LENGTH_SHORT).show();

            startActivity(new Intent(this, MainActivity.class));

            setResult(RESULT_OK);
            finish();
        }
    }

    @Override
    public void onErrorResponse(Exception exception) {
        Toast.makeText(this, R.string.create_account_error, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                case REQUEST_CODE_SELECT_PICTURE:
                    boolean isCamera;
                    if (data == null) {
                        isCamera = true;
                    } else {
                        String action = data.getAction();
                        if (action == null) {
                            isCamera = false;
                        } else {
                            isCamera = action.equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                        }
                    }

                    if (isCamera) {
                        startCropImage(Uri.fromFile(rawImageFile));
                    } else {
                        startCropImage(data == null ? null : data.getData());
                    }

                    break;

                case REQUEST_CODE_CROP_IMAGE:
                    Bitmap bitmap = BitmapFactory.decodeFile(avatarImageFile.getAbsolutePath());
                    RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
                    drawable.setCircular(true);
                    uploadAvatarButton.setImageDrawable(drawable);

                    break;
            }
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private void startCropImage(Uri source) {
        if (source != null) {
            int size = getResources().getDimensionPixelSize(R.dimen.default_avatar_size);
            CropImageIntentBuilder cropImage = new CropImageIntentBuilder(size, size, Uri.fromFile(avatarImageFile));
            cropImage.setSourceImage(source);

            startActivityForResult(cropImage.getIntent(this), REQUEST_CODE_CROP_IMAGE);
        }
    }

    private byte[] getAvatarBytes() {
        if (!avatarImageFile.exists()) return null;

        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(avatarImageFile);
        } catch (FileNotFoundException e) {
            AppLog.e("avatar file not found", e);
        }

        byte[] buffer = new byte[1024];
        int bytesRead;
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return output.toByteArray();
    }

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

        if (signupTask != null) {
            signupTask.dismissDialogAndCancel();
        }
    }
}

SignupTaskActivity は次のとおりです。

public class SignupTask extends BaseAsyncTask<Void, Void, Boolean> {
    private String user;
    private String name;
    private String password;
    private byte[] avatar;

    private ProgressDialog dialog;

    public SignupTask(Listener<Boolean> listener, Context context, String user, String password, String name, byte[] avatar) {
        super(listener, context);

        this.user = user;
        this.name = name;
        this.password = password;
        this.avatar = avatar;

        dialog = ProgressDialog.show(context, null, context.getResources().getString(R.string.signup));
    }

    @Override
    public Response<Boolean> doInBackground(Void... params) {
        Context context = getContext();
        if (context != null) {
            try {
                SmackHelper.getInstance(context).signupAndLogin(user, password, name, avatar);

                if (avatar != null) {
                    ImageCache.addAvatarToFile(context, user, BitmapFactory.decodeByteArray(avatar, 0, avatar.length));
                }

                PreferenceUtils.setLoginUser(context, user, password, name);

                return Response.success(true); 
            } catch(SmackInvocationException e) {
                AppLog.e(String.format("sign up error %s", e.toString()), e);

                return Response.error(e);
            }
        }

        return null;
    }

    @Override
    protected void onPostExecute(Response<Boolean> response) {
        dismissDialog();

        super.onPostExecute(response);
    }

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

        dismissDialog();
    }

    public void dismissDialog() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    public void dismissDialogAndCancel() {
        dismissDialog();
        cancel(false);
    }
}

SmackHelper クラスは次のとおりです。

public class SmackHelper {
    private static final String LOG_TAG = "SmackHelper";

    private static final int PORT = 5222;

    public static final String RESOURCE_PART = "Smack";

    private XMPPConnection con;

    private ConnectionListener connectionListener;

    private Context context;

    private State state;

    private PacketListener messagePacketListener;

    private PacketListener presencePacketListener;

    private SmackAndroid smackAndroid;

    private static SmackHelper instance;

    private SmackContactHelper contactHelper;

    private SmackVCardHelper vCardHelper;

    private FileTransferManager fileTransferManager;

    private PingManager pingManager;

    private long lastPing = new Date().getTime();

    public static final String ACTION_CONNECTION_CHANGED = "com.mstr.letschat.intent.action.CONNECTION_CHANGED";
    public static final String EXTRA_NAME_STATE = "com.mstr.letschat.State";

    private SmackHelper(Context context) {
        this.context = context;

        smackAndroid = SmackAndroid.init(context);

        messagePacketListener = new MessagePacketListener(context);
        presencePacketListener = new PresencePacketListener(context);

        SmackConfiguration.setDefaultPacketReplyTimeout(20 * 1000);
        Roster.setDefaultSubscriptionMode(SubscriptionMode.manual);

        ProviderManager.addExtensionProvider(UserLocation.ELEMENT_NAME, UserLocation.NAMESPACE, new LocationMessageProvider());
    }

    public static synchronized SmackHelper getInstance(Context context) {
        if (instance == null) {
            instance = new SmackHelper(context.getApplicationContext());
        }

        return instance;
    }

    public void setState(State state) {
        if (this.state != state) {
            Log.d(LOG_TAG, "enter state: " + state.name());

            this.state = state;
        }
    }

    public void signupAndLogin(String user, String password, String nickname, byte[] avatar) throws SmackInvocationException {
        connect();

        Map<String, String> attributes = new HashMap<String, String>();
        attributes.put("name", nickname);
        try {
            AccountManager.getInstance(con).createAccount(user, password, attributes);
        } catch (Exception e) {
            throw new SmackInvocationException(e);
        }

        login(user, password);

        vCardHelper.save(nickname, avatar);
    }

    public void sendChatMessage(String to, String body, PacketExtension packetExtension) throws SmackInvocationException {
        Message message = new Message(to, Message.Type.chat);
        message.setBody(body);
        if (packetExtension != null) {
            message.addExtension(packetExtension);
        }
        try {
            con.sendPacket(message);
        } catch (NotConnectedException e) {
            throw new SmackInvocationException(e);
        }
    }

    public List<RosterEntry> getRosterEntries() {
        List<RosterEntry> result = new ArrayList<RosterEntry>();

        Roster roster = con.getRoster();
        Collection<RosterGroup> groups = roster.getGroups();
        for (RosterGroup group : groups) {
            result.addAll(group.getEntries());
        }

        return result;
    }

最後に、私のメニフェスト ファイル public UserProfile search(String username) throws SmackInvocationException { String name = StringUtils.parseName(username); 文字列 jid = null; if (name == null || name.trim().length() == 0) { jid = ユーザー名 + "@" + con.getServiceName(); } else { jid = StringUtils.parseBareAddress(ユーザー名); }

    if (vCardHelper == null) {
        return null;
    }

    VCard vCard = vCardHelper.loadVCard(jid);
    String nickname = vCard.getNickName();

    return nickname == null ? null : new UserProfile(jid, vCard);
}

public String getNickname(String jid) throws SmackInvocationException {
    VCard vCard = vCardHelper.loadVCard(jid);

    return vCard.getNickName();
}

private void connect() throws SmackInvocationException {
    if (!isConnected()) {
        setState(State.CONNECTING);

        if (con == null) {
            con = createConnection();
        }

        try {
            con.connect();
        }catch (SmackException.NoResponseException er){
            Log.e(LOG_TAG,"Norespponse exception");
        }
        catch(Exception e) {
            Log.e(LOG_TAG, String.format("Unhandled exception %s", e.toString()), e);

            startReconnectIfNecessary();

            throw new SmackInvocationException(e);
        }
    }
}

@SuppressLint("TrulyRandom")
private XMPPConnection createConnection() {
    ConnectionConfiguration config = new ConnectionConfiguration(PreferenceUtils.getServerHost(context), PORT);

    SSLContext sc = null;
    MemorizingTrustManager mtm = null;
    try {
        mtm = new MemorizingTrustManager(context);
        sc = SSLContext.getInstance("TLS");
        sc.init(null, new X509TrustManager[] { mtm }, new SecureRandom());
    } catch (NoSuchAlgorithmException e) {
        throw new IllegalStateException(e);
    } catch (KeyManagementException e) {
        throw new IllegalStateException(e);
    }

    config.setCustomSSLContext(sc);
    config.setHostnameVerifier(mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()));
    config.setSecurityMode(SecurityMode.required);
    config.setReconnectionAllowed(false);
    config.setSendPresence(false);
    config.setSecurityMode(SecurityMode.disabled);
    List<HostAddress> list = config.getHostAddresses();
    boolean data = config.isSendPresence();


    return new XMPPTCPConnection(config);
}

public void cleanupConnection() {
    if (con != null) {
        con.removePacketListener(messagePacketListener);
        con.removePacketListener(presencePacketListener);

        if (connectionListener != null) {
            con.removeConnectionListener(connectionListener);
        }
    }

    if (isConnected()) {
        try {
            con.disconnect();
        } catch (NotConnectedException e) {}
    }
}

private void onConnectionEstablished() {
    if (state != State.CONNECTED) {
        //processOfflineMessages();

        try {
            con.sendPacket(new Presence(Presence.Type.available));
        } catch (NotConnectedException e) {}

        contactHelper = new SmackContactHelper(context, con);
        vCardHelper = new SmackVCardHelper(context, con);
        fileTransferManager = new FileTransferManager(con);
        OutgoingFileTransfer.setResponseTimeout(30000);
        addFileTransferListener();

        pingManager = PingManager.getInstanceFor(con);
        pingManager.registerPingFailedListener(new PingFailedListener() {
            @Override
            public void pingFailed() {
                // Note: remember that maybeStartReconnect is called from a different thread (the PingTask) here, it may causes synchronization problems
                long now = new Date().getTime();
                if (now - lastPing > 30000) {
                    Log.e(LOG_TAG, "Ping failure, reconnect");
                    startReconnectIfNecessary();
                    lastPing = now;
                } else {
                    Log.e(LOG_TAG, "Ping failure reported too early. Skipping this occurrence.");
                }
            }
        });

        con.addPacketListener(messagePacketListener, new MessageTypeFilter(Message.Type.chat));
        con.addPacketListener(presencePacketListener, new PacketTypeFilter(Presence.class));
        con.addConnectionListener(createConnectionListener());

        setState(State.CONNECTED);

        broadcastState(State.CONNECTED);

        MessageService.reconnectCount = 0;
    }
}

private void broadcastState(State state) {
    Intent intent = new Intent(ACTION_CONNECTION_CHANGED);
    intent.putExtra(EXTRA_NAME_STATE, state.toString());
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}

public void login(String username, String password) throws SmackInvocationException {
    connect();

    try {
        if (!con.isAuthenticated()) {
            con.login(username, password, RESOURCE_PART);
        }

        onConnectionEstablished();
    } catch(Exception e) {
        SmackInvocationException exception = new SmackInvocationException(e);
        // this is caused by wrong username/password, do not reconnect
        if (exception.isCausedBySASLError()) {
            cleanupConnection();
        } else {
            startReconnectIfNecessary();
        }

        throw exception;
    }
}

public String getLoginUserNickname() throws SmackInvocationException {
    try {
        return AccountManager.getInstance(con).getAccountAttribute("name");
    } catch (Exception e) {
        throw new SmackInvocationException(e);
    }
}

private void processOfflineMessages() {
    Log.i(LOG_TAG, "Begin retrieval of offline messages from server");

    OfflineMessageManager offlineMessageManager = new OfflineMessageManager(con);
    try {
        if (!offlineMessageManager.supportsFlexibleRetrieval()) {
            Log.d(LOG_TAG, "Offline messages not supported");
            return;
        }

        List<Message> msgs = offlineMessageManager.getMessages();
        for (Message msg : msgs) {
            Intent intent = new Intent(MessageService.ACTION_MESSAGE_RECEIVED, null, context, MessageService.class);
            intent.putExtra(MessageService.EXTRA_DATA_NAME_FROM, StringUtils.parseBareAddress(msg.getFrom()));
            intent.putExtra(MessageService.EXTRA_DATA_NAME_MESSAGE_BODY, msg.getBody());

            context.startService(intent);
        }

        offlineMessageManager.deleteMessages();
    } catch (Exception e) {
        Log.e(LOG_TAG, "handle offline messages error ", e);
    }

    Log.i(LOG_TAG, "End of retrieval of offline messages from server");
}

private ConnectionListener createConnectionListener() {
    connectionListener = new ConnectionListener() {
        @Override
        public void authenticated(XMPPConnection arg0) {}

        @Override
        public void connected(XMPPConnection arg0) {}

        @Override
        public void connectionClosed() {
            Log.e(LOG_TAG, "connection closed");
        }

        @Override
        public void connectionClosedOnError(Exception arg0) {
            // it may be due to network is not available or server is down, update state to WAITING_TO_CONNECT
            // and schedule an automatic reconnect
            Log.e(LOG_TAG, "connection closed due to error ", arg0);

            startReconnectIfNecessary();
        }

        @Override
        public void reconnectingIn(int arg0) {}

        @Override
        public void reconnectionFailed(Exception arg0) {}

        @Override
        public void reconnectionSuccessful() {}
    };

    return connectionListener;
}

private void startReconnectIfNecessary() {
    cleanupConnection();

    setState(State.WAITING_TO_CONNECT);

    if (NetworkUtils.isNetworkConnected(context)) {
        context.startService(new Intent(MessageService.ACTION_RECONNECT, null, context, MessageService.class));
    }
}

private boolean isConnected() {
    return con != null && con.isConnected();
}

public void onNetworkDisconnected() {
    setState(State.WAITING_FOR_NETWORK);
}

public void requestSubscription(String to, String nickname) throws SmackInvocationException {
    contactHelper.requestSubscription(to, nickname);
}

public void approveSubscription(String to, String nickname, boolean shouldRequest) throws SmackInvocationException {
    contactHelper.approveSubscription(to);

    if (shouldRequest) {
        requestSubscription(to, nickname);
    }
}

public void delete(String jid) throws SmackInvocationException {
    contactHelper.delete(jid);
}

public String loadStatus() throws SmackInvocationException {
    if (vCardHelper == null) {
        throw new SmackInvocationException("server not connected");
    }
    return vCardHelper.loadStatus();
}

public VCard loadVCard(String jid) throws SmackInvocationException {
    if (vCardHelper == null) {
        throw new SmackInvocationException("server not connected");
    }

    return vCardHelper.loadVCard(jid);
}

public VCard loadVCard() throws SmackInvocationException {
    if (vCardHelper == null) {
        throw new SmackInvocationException("server not connected");
    }

    return vCardHelper.loadVCard();
}

public void saveStatus(String status) throws SmackInvocationException {
    if (vCardHelper == null) {
        throw new SmackInvocationException("server not connected");
    }

    vCardHelper.saveStatus(status);

    contactHelper.broadcastStatus(status);
}

public SubscribeInfo processSubscribe(String from) throws SmackInvocationException {
    SubscribeInfo result = new SubscribeInfo();

    RosterEntry rosterEntry = contactHelper.getRosterEntry(from);
    ItemType rosterType = rosterEntry != null ? rosterEntry.getType() : null;

    if (rosterEntry == null || rosterType == ItemType.none) {
        result.setType(SubscribeInfo.TYPE_WAIT_FOR_APPROVAL);
        result.setNickname(getNickname(from));
    } else if (rosterType == ItemType.to) {
        result.setType(SubscribeInfo.TYPE_APPROVED);
        result.setNickname(rosterEntry.getName());

        approveSubscription(from, null, false);
    }

    result.setFrom(from);
    return result;
}

public void sendImage(File file, String to) throws SmackInvocationException {
    if (fileTransferManager == null || !isConnected()) {
        throw new SmackInvocationException("server not connected");
    }

    String fullJid = to + "/" + RESOURCE_PART;
    OutgoingFileTransfer transfer = fileTransferManager.createOutgoingFileTransfer(fullJid);
    try {
        transfer.sendFile(file, file.getName());
    } catch (SmackException e) {
        Log.e(LOG_TAG, "send file error");
        throw new SmackInvocationException(e);
    }

    while(!transfer.isDone()) {
        if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
                || transfer.getStatus().equals(Status.cancelled)){
            throw new SmackInvocationException("send file error, " + transfer.getError());
        }
    }

    Log.d(LOG_TAG, "send file status: " + transfer.getStatus());
    if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
            || transfer.getStatus().equals(Status.cancelled)){
        throw new SmackInvocationException("send file error, " + transfer.getError());
    }
}

private void addFileTransferListener() {
    fileTransferManager.addFileTransferListener(new FileTransferListener() {
        public void fileTransferRequest(final FileTransferRequest request) {
            new Thread() {
                @Override
                public void run() {
                    IncomingFileTransfer transfer = request.accept();
                    String fileName = String.valueOf(System.currentTimeMillis());
                    File file = new File(FileUtils.getReceivedImagesDir(context), fileName + FileUtils.IMAGE_EXTENSION);
                    try {
                        transfer.recieveFile(file);
                    } catch (SmackException e) {
                        Log.e(LOG_TAG, "receive file error", e);
                        return;
                    }

                    while (!transfer.isDone()) {
                        if(transfer.getStatus().equals(Status.refused) || transfer.getStatus().equals(Status.error)
                                || transfer.getStatus().equals(Status.cancelled)){
                            Log.e(LOG_TAG, "receive file error, " + transfer.getError());
                            return;
                        }
                    }

                    // start service to save the image to sqlite
                    if (transfer.getStatus().equals(Status.complete)) {
                        Intent intent = new Intent(MessageService.ACTION_MESSAGE_RECEIVED, null, context, MessageService.class);
                        intent.putExtra(MessageService.EXTRA_DATA_NAME_FROM, StringUtils.parseBareAddress(request.getRequestor()));
                        intent.putExtra(MessageService.EXTRA_DATA_NAME_MESSAGE_BODY, context.getString(R.string.image_message_body));
                        intent.putExtra(MessageService.EXTRA_DATA_NAME_FILE_PATH, file.getAbsolutePath());
                        intent.putExtra(MessageService.EXTRA_DATA_NAME_TYPE, ChatMessageTableHelper.TYPE_INCOMING_IMAGE);

                        context.startService(intent);
                    }

                }
            }.start();
        }
    });
}

public void onDestroy() {
    cleanupConnection();

    smackAndroid.onDestroy();
}

public static enum State {
    CONNECTING,

    CONNECTED,

    DISCONNECTED,

    // this is a state that client is trying to reconnect to server
    WAITING_TO_CONNECT,

    WAITING_FOR_NETWORK;
}

}

しかし、私は進歩を見つけることができませんでした.助けてください. 前もって感謝します。

4

1 に答える 1

1

闘争の後、私はこの種の問題の解決策を見つけました。次のようなサーバー側の変更を行う必要があります。 ここに画像の説明を入力

ステップ2: ここに画像の説明を入力

ステップ3: ここに画像の説明を入力

これらのすべての手順を実行すると、サーバーに新しいユーザーを登録できejabberdます。

于 2016-12-08T12:23:55.327 に答える