This commit is contained in:
Paul Schaub 2019-05-18 10:06:16 +02:00
parent 3c817a3172
commit ac2037e06c
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
39 changed files with 291 additions and 169 deletions

View File

@ -9,7 +9,7 @@ android {
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
}
@ -71,30 +71,33 @@ check.configure {
// Dependency versions are located in version.gradle
dependencies {
/*
architecture components for database and lifecycle management
*/
// architecture components for database and lifecycle management
implementation "android.arch.lifecycle:extensions:$archCompVersion"
implementation "android.arch.persistence.room:runtime:$archCompVersion"
implementation "android.arch.lifecycle:extensions:$archCompVersion"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycleVersion"
annotationProcessor "android.arch.lifecycle:compiler:$archCompVersion"
annotationProcessor "android.arch.persistence.room:compiler:$archCompVersion"
// Room
implementation "androidx.room:room-runtime:$roomVersion"
annotationProcessor "androidx.room:room-compiler:$roomVersion"
// Dagger 2 for dependency injection
implementation "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
// support libraries
implementation "com.android.support:appcompat-v7:$supportLibVersion"
implementation "com.android.support:design:$supportLibVersion"
implementation "com.android.support:support-v4:$supportLibVersion"
implementation "com.android.support:support-vector-drawable:$supportLibVersion"
implementation "com.android.support:cardview-v7:$supportLibVersion"
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.0.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
// circular image viewer for avatars
implementation 'de.hdodenhof:circleimageview:2.2.0'

View File

@ -1,8 +1,8 @@
package org.mercury_im.messenger;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"

View File

@ -1,10 +1,11 @@
package org.mercury_im.messenger.persistence.database;
import android.arch.persistence.room.Database;
import android.arch.persistence.room.Room;
import android.arch.persistence.room.RoomDatabase;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import org.mercury_im.messenger.persistence.database.dao.AccountDao;
import org.mercury_im.messenger.persistence.database.dao.RosterEntryDao;
import org.mercury_im.messenger.persistence.database.model.AccountModel;

View File

@ -1,13 +1,13 @@
package org.mercury_im.messenger.persistence.database.dao;
import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.TypeConverters;
import android.arch.persistence.room.Update;
import android.support.annotation.WorkerThread;
import androidx.lifecycle.LiveData;
import androidx.annotation.WorkerThread;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.TypeConverters;
import androidx.room.Update;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.database.model.AccountModel;
@ -42,7 +42,7 @@ public interface AccountDao {
LiveData<AccountModel> getAccountByJid(EntityBareJid jid);
@Insert
void insertAccount(AccountModel account);
long insertAccount(AccountModel account);
@Update
void updateAccount(AccountModel account);

View File

@ -1,18 +1,18 @@
package org.mercury_im.messenger.persistence.database.dao;
import android.arch.lifecycle.LiveData;
import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.TypeConverters;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.TypeConverters;
import org.mercury_im.messenger.persistence.database.type_converter.EntityBareJidConverter;
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
import java.util.List;
import static android.arch.persistence.room.OnConflictStrategy.REPLACE;
import static androidx.room.OnConflictStrategy.REPLACE;
@Dao
@TypeConverters(EntityBareJidConverter.class)

View File

@ -1,9 +1,10 @@
package org.mercury_im.messenger.persistence.database.model;
import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;
import android.arch.persistence.room.TypeConverters;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import androidx.room.TypeConverters;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.database.type_converter.EntityBareJidConverter;

View File

@ -1,14 +1,15 @@
package org.mercury_im.messenger.persistence.database.model;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.ForeignKey;
import android.arch.persistence.room.PrimaryKey;
import android.arch.persistence.room.TypeConverters;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.PrimaryKey;
import androidx.room.TypeConverters;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.database.type_converter.EntityBareJidConverter;
import static android.arch.persistence.room.ForeignKey.CASCADE;
import static androidx.room.ForeignKey.CASCADE;
@Entity(foreignKeys = @ForeignKey(entity = AccountModel.class,
parentColumns = "id",

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.database.type_converter;
import android.arch.persistence.room.TypeConverter;
import androidx.room.TypeConverter;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.impl.JidCreate;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.database.type_converter;
import android.arch.persistence.room.TypeConverter;
import androidx.room.TypeConverter;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.repository.account;
import android.arch.lifecycle.LiveData;
import androidx.lifecycle.LiveData;
import org.mercury_im.messenger.persistence.database.model.AccountModel;
@ -12,5 +12,5 @@ public interface AccountRepository {
LiveData<List<AccountModel>> getAllAccounts();
void insertAccount(AccountModel accountModel);
long insertAccount(AccountModel accountModel);
}

View File

@ -1,12 +1,13 @@
package org.mercury_im.messenger.persistence.repository.account;
import android.arch.lifecycle.LiveData;
import androidx.lifecycle.LiveData;
import android.os.AsyncTask;
import org.mercury_im.messenger.persistence.database.dao.AccountDao;
import org.mercury_im.messenger.persistence.database.model.AccountModel;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.inject.Inject;
@ -30,12 +31,19 @@ public class AccountRepositoryImpl implements AccountRepository {
}
@Override
public void insertAccount(AccountModel accountModel) {
public long insertAccount(AccountModel accountModel) {
InsertAsyncTask task = new InsertAsyncTask(accountDao);
task.execute(accountModel);
try {
return task.execute(accountModel).get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
return -1;
}
private static class InsertAsyncTask extends AsyncTask<AccountModel, Void, Void> {
private static class InsertAsyncTask extends AsyncTask<AccountModel, Void, Long> {
private final AccountDao accountDao;
@ -44,9 +52,9 @@ public class AccountRepositoryImpl implements AccountRepository {
}
@Override
protected Void doInBackground(AccountModel... accountModels) {
protected Long doInBackground(AccountModel... accountModels) {
for (AccountModel accountModel : accountModels) {
accountDao.insertAccount(accountModel);
return accountDao.insertAccount(accountModel);
}
return null;
}

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.repository.roster;
import android.arch.lifecycle.LiveData;
import androidx.lifecycle.LiveData;
import org.jivesoftware.smack.roster.RosterEntry;
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.persistence.repository.roster;
import android.arch.lifecycle.LiveData;
import androidx.lifecycle.LiveData;
import org.mercury_im.messenger.persistence.database.dao.RosterEntryDao;
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;

View File

@ -5,18 +5,28 @@ import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import android.util.Log;
import android.util.LongSparseArray;
import android.widget.Toast;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.Notifications;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.database.AppDatabase;
import org.mercury_im.messenger.ui.MainActivity;
import java.io.IOException;
import java.net.InetAddress;
import javax.inject.Inject;
/**
@ -25,26 +35,31 @@ import javax.inject.Inject;
*/
public class XmppService extends Service {
private static final String TAG = MercuryImApplication.TAG;
private static final String TAG = MercuryImApplication.TAG;
private static final String APP = "org.olomono.mercury";
private static final String SERVICE = APP + ".XmppService";
private static final String APP = "org.olomono.mercury";
private static final String SERVICE = APP + ".XmppService";
private static final String ACTION = SERVICE + ".ACTION";
private static final String EVENT = SERVICE + ".EVENT";
private static final String STATUS = SERVICE + ".STATUS";
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";
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";
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";
public static final String EVENT_INCOMING_MESSAGE = ".INCOMING_MESSAGE";
public static final String EVENT_OUTGOING_MESSAGE = ".OUTGOING_MESSAGE";
public static final String EVENT_INCOMING_MESSAGE = EVENT + ".INCOMING_MESSAGE";
public static final String EVENT_OUTGOING_MESSAGE = EVENT + ".OUTGOING_MESSAGE";
public static final String STATUS_SUCCESS = STATUS + ".SUCCESS";
public static final String STATUS_FAILURE = STATUS + ".FAILURE";
public static final String EXTRA_JID = EXTRA + ".JID";
public static final String EXTRA_PASSWORD = EXTRA + ".PASSWORD";
public static final String EXTRA_ACCOUNT_ID = EXTRA + ".ACCOUNT_ID";
public static final String STATUS_SUCCESS = STATUS + ".SUCCESS";
public static final String STATUS_FAILURE = STATUS + ".FAILURE";
@Inject
AppDatabase database;
@ -81,7 +96,70 @@ public class XmppService extends Service {
case ACTION_STOP:
stopForeground(true);
break;
case ACTION_CONNECT:
String jid = intent.getStringExtra(EXTRA_JID);
EntityBareJid bareJid = JidCreate.entityBareFromOrNull(jid);
if (jid == null) {
Toast.makeText(this, "No JID provided.", Toast.LENGTH_SHORT).show();
return START_STICKY_COMPATIBILITY;
}
String password = intent.getStringExtra(EXTRA_PASSWORD);
if (password == null) {
Toast.makeText(this, "No Password provided.", Toast.LENGTH_SHORT).show();
return START_STICKY_COMPATIBILITY;
}
long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
if (accountId == -1) {
Toast.makeText(this, "No account ID provided.", Toast.LENGTH_SHORT).show();
return START_STICKY_COMPATIBILITY;
}
new Thread() {
public void run() {
XMPPTCPConnection con = null;
try
{
InetAddress address = InetAddress.getByName(bareJid.getDomain().toString());
XMPPTCPConnectionConfiguration conf = XMPPTCPConnectionConfiguration.builder()
.setXmppDomain(bareJid.asDomainBareJid())
.setUsernameAndPassword(bareJid.getLocalpart().toString(), password)
.setHostAddress(address)
.setConnectTimeout(2 * 60 * 1000)
.build();
con = new XMPPTCPConnection(conf);
con.connect().login();
} catch(
XMPPException e)
{
e.printStackTrace();
} catch(
SmackException e)
{
e.printStackTrace();
} catch(
IOException e)
{
e.printStackTrace();
} catch(
InterruptedException e)
{
e.printStackTrace();
}
connections.put(intent.getLongExtra(EXTRA_ACCOUNT_ID,-1),con);
while (true) {
}
}
}.start();
break;
default:
break;
}

View File

@ -1,11 +1,13 @@
package org.mercury_im.messenger.ui;
import androidx.lifecycle.Observer;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import androidx.annotation.Nullable;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@ -55,6 +57,15 @@ public class MainActivity extends AppCompatActivity {
accountRepository.insertAccount(account);
}
});
accountRepository.getAllAccounts().observe(this, new Observer<List<AccountModel>>() {
@Override
public void onChanged(@Nullable List<AccountModel> accountModels) {
if (accountModels == null || accountModels.isEmpty()) {
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
}
}
});
}
@Override
@ -89,24 +100,6 @@ public class MainActivity extends AppCompatActivity {
new addRosterEntry(database).execute(rosterEntry);
}
private static class ifNoAccountsThen extends AsyncTask<Runnable, Void, Void> {
private final AppDatabase database;
public ifNoAccountsThen(AppDatabase database) {
this.database = database;
}
@Override
protected Void doInBackground(Runnable... runnables) {
List<AccountModel> accounts = database.accountDao().getAllAccounts().getValue();
if (accounts == null || accounts.size() == 0) {
runnables[0].run();
}
return null;
}
}
private static class addRosterEntry extends AsyncTask<RosterEntryModel, Void, Void> {
private AppDatabase database;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.ui.chat;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import org.mercury_im.messenger.R;

View File

@ -1,12 +1,12 @@
package org.mercury_im.messenger.ui.chat;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
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;
import android.view.ViewGroup;

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.ui.chat;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class ChatInputViewModel extends ViewModel {

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.ui.chat;
import android.arch.lifecycle.ViewModel;
import androidx.lifecycle.ViewModel;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.database.model.Account;

View File

@ -1,8 +1,9 @@
package org.mercury_im.messenger.ui.login;
import android.arch.lifecycle.ViewModelProviders;
import androidx.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
@ -14,13 +15,22 @@ import android.widget.TextView;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.database.model.AccountModel;
import org.mercury_im.messenger.persistence.repository.account.AccountRepository;
import org.mercury_im.messenger.service.XmppService;
import javax.inject.Inject;
/**
* A login screen that offers login via email/password.
*/
public class LoginActivity extends AppCompatActivity implements TextView.OnEditorActionListener {
@Inject
AccountRepository accountRepository;
// UI references.
private AutoCompleteTextView mJidView;
private EditText mPasswordView;
@ -34,6 +44,8 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
MercuryImApplication.getApplication().getAppComponent().inject(this);
// Set up the login form.
mJidView = findViewById(R.id.jid);
mPasswordView = findViewById(R.id.password);
@ -69,22 +81,43 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
}
private void loginDetailsEntered() {
boolean loginIntact = true;
String jidInput = mJidView.getText().toString();
if (jidInput.isEmpty()) {
mJidView.setError(getResources().getString(R.string.error_field_required));
loginIntact = false;
}
EntityBareJid jid = asValidJidOrNull(jidInput);
if (jid == null) {
mJidView.setError(getResources().getString(R.string.error_invalid_jid));
loginIntact = false;
}
String password = mPasswordView.getText().toString();
if (!isPasswordValid(password)) {
mPasswordView.setError(getResources().getString(R.string.error_invalid_password));
loginIntact = false;
}
viewModel.login();
if (loginIntact) {
AccountModel accountModel = new AccountModel();
accountModel.setEnabled(true);
accountModel.setJid(jid);
accountModel.setPassword(password);
long id = accountRepository.insertAccount(accountModel);
attemptLogin(jid, password, id);
}
}
private void attemptLogin(EntityBareJid jid, String password, long accountId) {
Intent connectIntent = new Intent(getApplicationContext(), XmppService.class);
connectIntent.setAction(XmppService.ACTION_CONNECT);
connectIntent.putExtra(XmppService.EXTRA_JID, jid.toString());
connectIntent.putExtra(XmppService.EXTRA_PASSWORD, password);
connectIntent.putExtra(XmppService.EXTRA_ACCOUNT_ID, accountId);
startService(connectIntent);
}
/**

View File

@ -1,8 +1,8 @@
package org.mercury_im.messenger.ui.login;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;
import android.support.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import org.mercury_im.messenger.persistence.database.model.AccountModel;

View File

@ -1,11 +1,11 @@
package org.mercury_im.messenger.ui.roster;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.support.v7.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.ui.roster;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@ -1,9 +1,9 @@
package org.mercury_im.messenger.ui.roster;
import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.support.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.annotation.NonNull;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;

View File

@ -3,11 +3,11 @@ package org.mercury_im.messenger.ui.settings;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.appcompat.widget.Toolbar;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;

View File

@ -12,7 +12,7 @@ import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.support.v7.app.ActionBar;
import androidx.appcompat.app.ActionBar;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.RingtonePreference;

View File

@ -31,7 +31,7 @@
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -44,9 +44,9 @@
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<android.support.design.widget.TextInputLayout
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
@ -62,7 +62,7 @@
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/sign_in_button"

View File

@ -1,28 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<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.MainActivity">
<android.support.design.widget.AppBarLayout
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
<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" />
</android.support.design.widget.AppBarLayout>
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -30,4 +30,4 @@
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/chat"
@ -7,7 +7,7 @@
android:layout_height="match_parent"
tools:context=".ui.chat.ChatInputFragment">
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
@ -17,7 +17,7 @@
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/recycler_view_item_1">
</android.support.v7.widget.RecyclerView>
</androidx.recyclerview.widget.RecyclerView>
<FrameLayout
android:id="@+id/container_chat"
@ -32,4 +32,4 @@
</FrameLayout>
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout 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"
@ -7,14 +7,14 @@
tools:context=".ui.roster.RosterFragment"
tools:showIn="@layout/activity_main">
<android.support.v7.widget.RecyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/roster_entry_list__recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/recycler_view_item">
</android.support.v7.widget.RecyclerView>
</androidx.recyclerview.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
<androidx.constraintlayout.widget.ConstraintLayout
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"
@ -49,4 +49,4 @@
app:layout_constraintTop_toTopOf="@+id/imageView2"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp" />
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
<androidx.constraintlayout.widget.ConstraintLayout
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"
@ -49,4 +49,4 @@
app:layout_constraintTop_toTopOf="@+id/imageView2"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp" />
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
<androidx.constraintlayout.widget.ConstraintLayout
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"
@ -53,4 +53,4 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/roster_entry__avatar"
tools:text="@tools:sample/date/hhmm" />
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout 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"
@ -7,7 +7,7 @@
android:orientation="horizontal"
android:background="@null">
<android.support.design.widget.FloatingActionButton
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/chat_field__fab_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -22,7 +22,7 @@
app:layout_constraintVertical_bias="1.0"
app:srcCompat="@drawable/ic_add_white_24dp" />
<android.support.v7.widget.CardView
<androidx.cardview.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="0dp"
android:layout_height="wrap_content"
@ -34,7 +34,7 @@
card_view:cardElevation="6dp"
app:cardUseCompatPadding="true">
<android.support.constraint.ConstraintLayout
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="56dp">
@ -55,7 +55,7 @@
card_view:layout_constraintTop_toTopOf="parent"
tools:text="Open Protocols!" />
<android.support.v7.widget.AppCompatImageButton
<androidx.appcompat.widget.AppCompatImageButton
android:id="@+id/chat_field__button_send"
android:layout_width="56dp"
android:layout_height="56dp"
@ -65,8 +65,8 @@
app:srcCompat="@drawable/ic_send_black_24dp"
card_view:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
<androidx.constraintlayout.widget.ConstraintLayout
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"
@ -18,7 +18,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
@ -36,8 +36,8 @@
android:layout_margin="8dp"
tools:text="Hello World" />
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
<androidx.cardview.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
@ -22,6 +22,6 @@
android:layout_margin="8dp"
tools:text="Hello World!Hello World!Hello World!Hello World!" />
</android.support.v7.widget.CardView>
</androidx.cardview.widget.CardView>
</android.support.constraint.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -6,6 +6,8 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit

View File

@ -36,7 +36,8 @@ ext {
// Other libraries
// Architecture Components
archCompVersion = "1.1.1"
lifecycleVersion = "2.0.0"
roomVersion = "2.1.0-beta01"
// Dagger 2
daggerVersion = "2.17"