This commit is contained in:
Paul Schaub 2019-06-06 23:32:41 +02:00
parent 3e439bc378
commit c122e2db81
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
19 changed files with 163 additions and 154 deletions

View File

@ -17,12 +17,11 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".service.XmppBoundService"
android:enabled="true"
android:exported="false"></service>
<activity android:name=".ui.chat.ChatActivity"></activity>
<activity
android:name=".ui.chat.ChatActivity"
android:label="Chat"
android:theme="@style/AppTheme.NoActionBar"/>
<activity
android:name=".ui.MainActivity"
android:label="@string/title_activity_main"
@ -41,7 +40,7 @@
android:label="@string/title_activity_login" />
<activity android:name=".ui.login.AccountsActivity" />
<service android:name=".service.XmppStartedService" />
<service android:name=".service.XmppConnectionService" />
</application>
</manifest>

View File

@ -12,7 +12,7 @@ import org.mercury_im.messenger.di.component.DaggerAppComponent;
import org.mercury_im.messenger.di.module.AppModule;
import org.mercury_im.messenger.di.module.RepositoryModule;
import org.mercury_im.messenger.di.module.RoomModule;
import org.mercury_im.messenger.service.XmppStartedService;
import org.mercury_im.messenger.service.XmppConnectionService;
public class MercuryImApplication extends Application {
@ -39,9 +39,9 @@ public class MercuryImApplication extends Application {
appComponent.inject(this);
initializeNotificationChannels(this);
Intent serviceIntent = new Intent(getApplicationContext(), XmppStartedService.class);
Intent serviceIntent = new Intent(getApplicationContext(), XmppConnectionService.class);
serviceIntent.setAction(XmppStartedService.ACTION_START);
serviceIntent.setAction(XmppConnectionService.ACTION_START);
if (Build.VERSION.SDK_INT < 26) {
startService(serviceIntent);
} else {

View File

@ -4,7 +4,7 @@ import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.di.module.AppModule;
import org.mercury_im.messenger.di.module.RepositoryModule;
import org.mercury_im.messenger.di.module.RoomModule;
import org.mercury_im.messenger.service.XmppStartedService;
import org.mercury_im.messenger.service.XmppConnectionService;
import org.mercury_im.messenger.ui.MainActivity;
import org.mercury_im.messenger.ui.chat.ChatActivity;
import org.mercury_im.messenger.ui.chat.ChatInputFragment;
@ -22,7 +22,7 @@ import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(dependencies = {}, modules = {AppModule.class, RoomModule.class, RepositoryModule.class})
@Component(modules = {AppModule.class, RoomModule.class, RepositoryModule.class})
public interface AppComponent {
// Application
@ -58,7 +58,7 @@ public interface AppComponent {
// Services
void inject(XmppStartedService service);
void inject(XmppConnectionService service);
// Connectors

View File

@ -1,34 +0,0 @@
package org.mercury_im.messenger.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class XmppBoundService extends Service {
private final Binder binder = new Binder();
private XmppStartedService startedService;
public class Binder extends android.os.Binder {
public XmppBoundService getService() {
return XmppBoundService.this;
}
}
public XmppBoundService() {
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public void setXmppStartedService(XmppStartedService service) {
this.startedService = service;
}
public XmppStartedService getStartedService() {
return startedService;
}
}

View File

@ -7,6 +7,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@ -50,38 +51,40 @@ import java.util.Set;
import javax.inject.Inject;
/**
* Started Service, which is responsible for managing {@link XMPPConnection XMPPConnections}
* Started, Bound Service, which is responsible for managing {@link XMPPConnection XMPPConnections}
* affiliated with registered accounts.
*/
public class XmppStartedService extends Service {
public class XmppConnectionService extends Service {
private static final String TAG = MercuryImApplication.TAG;
private static final String APP = "org.olomono.mercury";
private static final String SERVICE = APP + ".XmppStartedService";
private static final String SERVICE = APP + ".XmppConnectionService";
private static final String ACTION = SERVICE + ".ACTION";
private static final String EVENT = SERVICE + ".EVENT";
private static final String EXTRA = SERVICE + ".EXTRA";
private static final String STATUS = SERVICE + ".STATUS";
// ACTIONS
public static final String ACTION_START = ACTION + ".START";
public static final String ACTION_STOP = ACTION + ".STOP";
public static final String ACTION_CONNECT = ACTION + ".CONNECT";
public static final String ACTION_DISCONNECT = ACTION + ".DISCONNECT";
public static final String ACTION_PING = ACTION + ".PING";
// EVENTS
public static final String EVENT_INCOMING_MESSAGE = EVENT + ".INCOMING_MESSAGE";
public static final String EVENT_OUTGOING_MESSAGE = EVENT + ".OUTGOING_MESSAGE";
// EXTRAS
public static final String EXTRA_CONFIGURATION = EXTRA + ".CONFIGURATION";
public static final String EXTRA_ACCOUNT_ID = EXTRA + ".ACCOUNT_ID";
// STATUSES
public static final String STATUS_SUCCESS = STATUS + ".SUCCESS";
public static final String STATUS_FAILURE = STATUS + ".FAILURE";
@Inject
AppDatabase database;
@Inject
ContactRepository rosterRepository;
@ -105,25 +108,8 @@ public class XmppStartedService extends Service {
super.onCreate();
Log.d(TAG, "onCreate()");
MercuryImApplication.getApplication().getAppComponent().inject(this);
Intent intent = new Intent(this, XmppBoundService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
XmppBoundService.Binder binder = (XmppBoundService.Binder) iBinder;
XmppBoundService boundService = binder.getService();
boundService.setXmppStartedService(XmppStartedService.this);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
@ -134,7 +120,7 @@ public class XmppStartedService extends Service {
switch (msg.what) {
case 1:
Message m = (Message) msg.obj;
Toast.makeText(XmppStartedService.this, (m.getFrom() != null ? m.getFrom().toString() : "null") + ": "
Toast.makeText(XmppConnectionService.this, (m.getFrom() != null ? m.getFrom().toString() : "null") + ": "
+ m.getBody(), Toast.LENGTH_LONG).show();
}
}

View File

@ -0,0 +1,7 @@
package org.mercury_im.messenger.service;
import android.os.Binder;
public class XmppConnectionServiceBinder extends Binder {
}

View File

@ -5,16 +5,26 @@ import android.os.Bundle;
import org.mercury_im.messenger.R;
public class ChatActivity extends AppCompatActivity {
public class ChatActivity extends AppCompatActivity implements ChatInputFragment.OnChatInputActionListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, ChatInputFragment.newInstance())
.commitNow();
}
}
@Override
public void onButtonMediaClicked() {
}
@Override
public void onComposingBodyChanged(String body) {
}
@Override
public void onComposingBodySend(String body) {
}
}

View File

@ -1,13 +1,11 @@
package org.mercury_im.messenger.ui.chat;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@ -18,11 +16,19 @@ import android.widget.Toast;
import org.mercury_im.messenger.R;
import butterknife.BindView;
import butterknife.OnClick;
public class ChatInputFragment extends Fragment implements View.OnClickListener {
private EditText textInput;
private ImageButton addAttachement;
private ImageButton buttonSend;
@BindView(R.id.text_body)
EditText textInput;
@BindView(R.id.btn_media)
ImageButton addAttachement;
@BindView(R.id.btn_send)
ImageButton buttonSend;
private ChatInputViewModel mViewModel;
@ -36,14 +42,7 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_chat, container, false);
textInput = view.findViewById(R.id.chat_field__text_input);
addAttachement = view.findViewById(R.id.chat_field__button_attachment);
buttonSend = view.findViewById(R.id.chat_field__button_send);
addAttachement.setOnClickListener(this);
buttonSend.setOnClickListener(this);
return view;
return inflater.inflate(R.layout.content_chat, container, false);
}
@Override
@ -53,15 +52,22 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener
observeViewModel(mViewModel);
}
/**
* Observe the {@link ChatInputViewModel} for changes and reflect those in the UI.
*
* @param viewModel ViewModel
*/
private void observeViewModel(ChatInputViewModel viewModel) {
viewModel.getDraft().observe(ChatInputFragment.this, new Observer<String>() {
@Override
public void onChanged(@Nullable String draft) {
textInput.setText(draft);
}
});
viewModel.getDraft().observe(ChatInputFragment.this, draft -> textInput.setText(draft));
}
/**
* Attach this fragment to the parent {@link android.app.Activity} which MUST implement
* {@link OnChatInputActionListener} and is bound to handle input actions like send button
* clicked etc.
*
* @param context parent activity
*/
@Override
public void onAttach(Context context) {
super.onAttach(context);
@ -80,18 +86,19 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener
}
@Override
@OnClick({R.id.btn_send, R.id.btn_media})
public void onClick(View view) {
switch (view.getId()) {
// Add media
case R.id.chat_field__button_attachment:
case R.id.btn_media:
if (actionListener != null) {
actionListener.onButtonAddAttachementClicked();
actionListener.onButtonMediaClicked();
}
Toast.makeText(getContext(), R.string.not_yet_implemented, Toast.LENGTH_SHORT).show();
break;
// Send message
case R.id.chat_field__button_send:
case R.id.btn_send:
if (actionListener != null) {
actionListener.onComposingBodySend(textInput.getText().toString());
}
@ -102,7 +109,7 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener
public interface OnChatInputActionListener {
void onButtonAddAttachementClicked();
void onButtonMediaClicked();
void onComposingBodyChanged(String body);

View File

@ -8,6 +8,7 @@ import org.mercury_im.messenger.persistence.model.AccountModel;
public class ChatViewModel extends ViewModel {
private AccountModel account;
private EntityBareJid contact;
public void init(AccountModel account, EntityBareJid contact) {

View File

@ -11,9 +11,7 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.google.android.material.textfield.TextInputEditText;
@ -25,7 +23,7 @@ import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.model.AccountModel;
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.service.XmppStartedService;
import org.mercury_im.messenger.service.XmppConnectionService;
import javax.inject.Inject;
@ -123,9 +121,9 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
}
private void attemptLogin(EntityBareJid jid, String password, long accountId) {
Intent connectIntent = new Intent(getApplicationContext(), XmppStartedService.class);
connectIntent.setAction(XmppStartedService.ACTION_CONNECT);
connectIntent.putExtra(XmppStartedService.EXTRA_ACCOUNT_ID, accountId);
Intent connectIntent = new Intent(getApplicationContext(), XmppConnectionService.class);
connectIntent.setAction(XmppConnectionService.ACTION_CONNECT);
connectIntent.putExtra(XmppConnectionService.EXTRA_ACCOUNT_ID, accountId);
startService(connectIntent);
}

View File

@ -1,7 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.chat.ChatActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.chat.ChatActivity" />
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_chat" />
<FrameLayout
android:id="@+id/fab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<include layout="@layout/view_chat_field"/>
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -20,17 +20,4 @@
</androidx.recyclerview.widget.RecyclerView>
<FrameLayout
android:id="@+id/container_chat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<include layout="@layout/view_chat_field"/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -24,7 +24,7 @@
android:minHeight="56dp">
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/chat_field__button_attachment"
android:id="@+id/btn_media"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@null"
@ -34,7 +34,7 @@
app:srcCompat="@drawable/ic_add_white_24dp" />
<EditText
android:id="@+id/chat_field__text_input"
android:id="@+id/text_body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
@ -44,13 +44,13 @@
android:inputType="textMultiLine|textAutoCorrect"
android:maxLines="6"
card_view:layout_constraintBottom_toBottomOf="parent"
card_view:layout_constraintEnd_toStartOf="@+id/chat_field__button_send"
card_view:layout_constraintStart_toEndOf="@+id/chat_field__button_attachment"
card_view:layout_constraintEnd_toStartOf="@+id/btn_send"
card_view:layout_constraintStart_toEndOf="@+id/btn_media"
card_view:layout_constraintTop_toTopOf="parent"
tools:text="Open Protocols!" />
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/chat_field__button_send"
android:id="@+id/btn_send"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@null"

View File

@ -1,5 +1,5 @@
<resources>
<string name="app_name">Messenger</string>
<string name="app_name">Mercury</string>
<string name="title_activity_login">Log in</string>
<!-- Strings related to login -->
<string name="prompt_jid">XMPP Address</string>

View File

@ -1,30 +1,50 @@
package org.mercury_im.messenger.persistence.room.model;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.model.ChatModel;
@Entity
@Entity(tableName = "chats", indices = {@Index("id")})
public class RoomChatModel implements ChatModel {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
long id;
long xmppIdentityId;
boolean isOpened;
@Override
public EntityBareJid getJid() {
return null;
public long getId() {
return id;
}
@Override
public void setJid(EntityBareJid jid) {
public void setId(long id) {
this.id = id;
}
@Override
public long getAccountId() {
return 0;
public long getXmppIdentityId() {
return xmppIdentityId;
}
@Override
public void setAccountId() {
public void setXmppIdentityId(long id) {
this.xmppIdentityId = id;
}
@Override
public boolean isOpened() {
return isOpened;
}
@Override
public void setOpened(boolean opened) {
this.isOpened = opened;
}
}

View File

@ -4,11 +4,15 @@ import org.jxmpp.jid.EntityBareJid;
public interface ChatModel {
EntityBareJid getJid();
long getId();
void setJid(EntityBareJid jid);
void setId(long id);
long getAccountId();
long getXmppIdentityId();
void setAccountId();
void setXmppIdentityId(long id);
boolean isOpened();
void setOpened(boolean opened);
}

View File

@ -6,6 +6,10 @@ import java.io.File;
public interface ContactModel {
long getId();
void setId(long id);
long getAccountId();
void setAccountId(long id);

View File

@ -13,23 +13,15 @@ import java.io.File;
*/
public interface XmppIdentityModel {
/**
* Return the JID of this identity.
* Should be part of the composited primary key.
*
* @return jid
*/
long getId();
void setId(long id);
@NonNull
EntityBareJid getJid();
void setJid(EntityBareJid jid);
/**
* Return the primary key of the account which is communicating with the
* {@link XmppIdentityModel}.
*
* @return accountId
*/
long getAccountId();
void setAccountId(long accountId);

View File

@ -12,7 +12,7 @@ public interface ChatRepository {
LiveData<List<ChatModel>> getAllChats();
void getChatWith(XmppIdentityModel identity);
LiveData<ChatModel> getChatWith(XmppIdentityModel identity);
void closeChat(ChatModel chat);
}