所以这是我的问题:我使用令牌生成了一个ChatClient实例,我想使用接收到的SID失败的实例加入该实例,并且出现以下错误
2019-01-25 16:37:17.812 15294-15294/com.twilio.chat.demo E/TwilioApplication: Login error. Error 0:1401 Unable to establish connection to Twilio Sync service
2019-01-25 16:37:17.848 15294-15459/com.twilio.chat.demo W/TWC: [2019-01-25 16:37:17.802] [rtd] [WARNING] -1997051536 | 26 | SyncList | request 1 error code 1401: Unable to establish connection to Twilio Sync service
2019-01-25 16:37:17.848 15294-15459/com.twilio.chat.demo W/TWC: [2019-01-25 16:37:17.802] [rtd] [WARNING] -1997051536 | IPM | session error 1401 Unable to establish connection to Twilio Sync service
我已经从twilio网站开始使用twilio chat quickstart android了。 我还创建了访问令牌URL来检索令牌。下面是我用于twilio聊天集成的主要活动代码。
public class MainActivity extends AppCompatActivity {
/*
Change this URL to match the token URL for your Twilio Function
*/
final static String SERVER_TOKEN_URL = "https://example.com/chat-token";
final static String DEFAULT_CHANNEL_NAME = "general";
final static String TAG = "TwilioChat";
// Update this identity for each individual user, for instance after they login
private String mIdentity = "CHAT_USER";
private RecyclerView mMessagesRecyclerView;
private MessagesAdapter mMessagesAdapter;
private ArrayList<Message> mMessages = new ArrayList<>();
private EditText mWriteMessageEditText;
private Button mSendChatMessageButton;
private ChatClient mChatClient;
private Channel mGeneralChannel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMessagesRecyclerView = (RecyclerView) findViewById(R.id.messagesRecyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// for a chat app, show latest at the bottom
layoutManager.setStackFromEnd(true);
mMessagesRecyclerView.setLayoutManager(layoutManager);
mMessagesAdapter = new MessagesAdapter();
mMessagesRecyclerView.setAdapter(mMessagesAdapter);
mWriteMessageEditText = (EditText) findViewById(R.id.writeMessageEditText);
mSendChatMessageButton = (Button) findViewById(R.id.sendChatMessageButton);
mSendChatMessageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mGeneralChannel != null) {
String messageBody = mWriteMessageEditText.getText().toString();
Message.Options options = Message.options().withBody(messageBody);
Log.d(TAG,"Message created");
mGeneralChannel.getMessages().sendMessage(options, new CallbackListener<Message>() {
@Override
public void onSuccess(Message message) {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// need to modify user interface elements on the UI thread
mWriteMessageEditText.setText("");
}
});
}
});
}
}
});
retrieveAccessTokenfromServer();
}
private void retrieveAccessTokenfromServer() {
String deviceId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
String tokenURL = SERVER_TOKEN_URL + "?device=" + deviceId + "&identity=" + mIdentity;
Ion.with(this)
.load(tokenURL)
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
@Override
public void onCompleted(Exception e, JsonObject result) {
if (e == null) {
String accessToken = result.get("token").getAsString();
Log.d(TAG, "Retrieved access token from server: " + accessToken);
setTitle(mIdentity);
ChatClient.Properties.Builder builder = new ChatClient.Properties.Builder();
ChatClient.Properties props = builder.createProperties();
ChatClient.create(MainActivity.this,accessToken,props,mChatClientCallback);
} else {
Log.e(TAG,e.getMessage(),e);
Toast.makeText(MainActivity.this,
R.string.error_retrieving_access_token, Toast.LENGTH_SHORT)
.show();
}
}
});
}
private void loadChannels() {
mChatClient.getChannels().getChannel(DEFAULT_CHANNEL_NAME, new CallbackListener<Channel>() {
@Override
public void onSuccess(Channel channel) {
if (channel != null) {
Log.d(TAG, "Joining Channel: " + DEFAULT_CHANNEL_NAME);
joinChannel(channel);
} else {
Log.d(TAG, "Creating Channel: " + DEFAULT_CHANNEL_NAME);
mChatClient.getChannels().createChannel(DEFAULT_CHANNEL_NAME,
Channel.ChannelType.PUBLIC, new CallbackListener<Channel>() {
@Override
public void onSuccess(Channel channel) {
if (channel != null) {
Log.d(TAG, "Joining Channel: " + DEFAULT_CHANNEL_NAME);
joinChannel(channel);
}
}
@Override
public void onError(ErrorInfo errorInfo) {
Log.e(TAG,"Error creating channel: " + errorInfo.getMessage());
}
});
}
}
@Override
public void onError(ErrorInfo errorInfo) {
Log.e(TAG,"Error retrieving channel: " + errorInfo.getMessage());
}
});
}
private void joinChannel(final Channel channel) {
Log.d(TAG, "Joining Channel: " + channel.getUniqueName());
channel.join(new StatusListener() {
@Override
public void onSuccess() {
mGeneralChannel = channel;
Log.d(TAG, "Joined default channel");
mGeneralChannel.addListener(mDefaultChannelListener);
}
@Override
public void onError(ErrorInfo errorInfo) {
Log.e(TAG,"Error joining channel: " + errorInfo.getMessage());
}
});
}
private CallbackListener<ChatClient> mChatClientCallback =
new CallbackListener<ChatClient>() {
@Override
public void onSuccess(ChatClient chatClient) {
mChatClient = chatClient;
loadChannels();
Log.d(TAG, "Success creating Twilio Chat Client");
}
@Override
public void onError(ErrorInfo errorInfo) {
Log.e(TAG,"Error creating Twilio Chat Client: " + errorInfo.getMessage());
}
};
private ChannelListener mDefaultChannelListener = new ChannelListener() {
@Override
public void onMessageAdded(final Message message) {
Log.d(TAG, "Message added");
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
// need to modify user interface elements on the UI thread
mMessages.add(message);
mMessagesAdapter.notifyDataSetChanged();
}
});
}
@Override
public void onMessageUpdated(Message message, Message.UpdateReason updateReason) {
Log.d(TAG, "Message updated: " + message.getMessageBody());
}
@Override
public void onMessageDeleted(Message message) {
Log.d(TAG, "Message deleted");
}
@Override
public void onMemberAdded(Member member) {
Log.d(TAG, "Member added: " + member.getIdentity());
}
@Override
public void onMemberUpdated(Member member, Member.UpdateReason updateReason) {
Log.d(TAG, "Member updated: " + member.getIdentity());
}
@Override
public void onMemberDeleted(Member member) {
Log.d(TAG, "Member deleted: " + member.getIdentity());
}
@Override
public void onTypingStarted(Channel channel, Member member) {
Log.d(TAG, "Started Typing: " + member.getIdentity());
}
@Override
public void onTypingEnded(Channel channel, Member member) {
Log.d(TAG, "Ended Typing: " + member.getIdentity());
}
@Override
public void onSynchronizationChanged(Channel channel) {
}
};
class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.ViewHolder> {
class ViewHolder extends RecyclerView.ViewHolder {
public TextView mMessageTextView;
public ViewHolder(TextView textView) {
super(textView);
mMessageTextView = textView;
}
}
public MessagesAdapter() {
}
@Override
public MessagesAdapter
.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
TextView messageTextView = (TextView) LayoutInflater.from(parent.getContext())
.inflate(R.layout.message_text_view, parent, false);
return new ViewHolder(messageTextView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message message = mMessages.get(position);
String messageText = String.format("%s: %s", message.getAuthor(), message.getMessageBody());
holder.mMessageTextView.setText(messageText);
}
@Override
public int getItemCount() {
return mMessages.size();
}
}
}
答案 0 :(得分:1)
嘿,在设置Twilio演示聊天应用程序时,我也遇到了这个问题。我正在使用https://github.com/twilio/twilio-chat-demo-android Android应用程序和https://github.com/TwilioDevEd/sdk-starter-ruby。我花了一点时间才发现我设置了ACCESS_TOKEN_SERVICE_URL=http://abc12345.ngrok.io
,而不仅仅是将ngrok复制粘贴到我的kotlin应用程序gradle.properties
文件中。当我应该查看sdk-starter-ruby应用程序中定义的路由时。在这种情况下,sinatra应用定义了一条路线
get '/token' do
# Create a random username for the client
identity = Faker::Internet.user_name
# Create an access token which we will sign and return to the client
token = generate_token(identity)
# Generate the token and send to client
json :identity => identity, :token => token
end
这是我需要作为该属性的URL输入的路由。
因此,这为我解决了该问题ACCESS_TOKEN_SERVICE_URL=http://abc12345.ngrok.io/token
您的SERVER_TOKEN_URL
转到https://example.com/chat-token
,因此应该指向生成令牌的服务器。这里有多种语言的示例:https://www.twilio.com/docs/chat/javascript/quickstart