DEV Community

HMS Community
HMS Community

Posted on

Expert: Directory App MVVM Jetpack (Firebase and Webrtc) in Android using Kotlin- Part-3

Overview

In this article, I will create a Directory android application using Kotlin in which I will integrate HMS Core kits such as HMS Account, AuthService, Identity Kit, Firebase Auth and Webrtc .

App will make use of android MVVM clean architecture using Jetpack components such as DataBinding, AndroidViewModel, Observer, LiveData and much more.

In this article we are going to implement DataBinding using Observable pattern.

FirebaseAuth Service Introduction

Firebase security applies Google’s internal expertise to easily build app sign-ins. Develop simple, multi-platform sign-in with Firebase Authentication. Build Fast For Any Device.

Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app.

WebRTC Service Introduction

WebRTC is a free and open-source project providing web browsers and mobile applications with real-time communication via application programming interfaces.

Prerequisite

Huawei Phone EMUI 3.0 or later.
Non-Huawei phones Android 4.4 or later (API level 19 or higher).
HMS Core APK 4.0.0.300 or later
Android Studio
AppGallery Account
App Gallery Integration process

  1. Sign In and Create or Choose a project on AppGallery Connect portal.​

  2. Navigate to Project settings and download the configuration file.​

  3. Navigate to General Information, and then provide Data Storage location.​

App Development

Add Required Dependencies:

Launch Android studio and create a new project. Once the project is ready.
Add following dependency for HMS Kits

//HMS Kits
implementation 'com.huawei.agconnect:agconnect-core:1.5.0.300'
implementation 'com.huawei.hms:hwid:5.3.0.302'
implementation 'com.huawei.hms:identity:5.3.0.300'
//Google Firebase    
implementation platform('com.google.firebase:firebase-bom:28.4.1')
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-auth'
    implementation 'com.google.firebase:firebase-database'
    implementation 'com.google.android.gms:play-services-auth:19.2.0'
    implementation 'com.airbnb.android:lottie:4.1.0'
    implementation 'com.mikhaellopez:circularimageview:4.3.0'
    implementation 'com.kaopiz:kprogresshud:1.2.0'
    implementation 'com.google.android.gms:play-services-ads:20.4.0'
    implementation 'com.github.bumptech.glide:glide:4.12.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
Enter fullscreen mode Exit fullscreen mode

Navigate to the Gradle scripts folder and open build.gradle (project: app)

repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.0.1"
        classpath 'com.huawei.agconnect:agcp:1.4.2.300'
Enter fullscreen mode Exit fullscreen mode

​​​​​​​Code Implementation

Created following package model, event, viewmodel.
ViewModel: The ViewModel makes it easy to update data changes on the UI.Create a package named viewmodel in your main folder.Then create a new file and name it LoginViewModel.kt along with their FactoryViewModelProviders.

MainActivity.kt:

package com.hms.directory
class MainActivity : AppCompatActivity(), ActivityNavigation {
    private lateinit var viewModel: LoginViewModel
    private lateinit var dataBinding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        dataBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        val viewModel: LoginViewModel by lazy {
            val activity = requireNotNull(this) {}
            ViewModelProviders.of(this, LoginViewModelFactory(activity.application))
                .get(LoginViewModel::class.java)
        }
        dataBinding.loginViewModel = viewModel
        dataBinding.lifecycleOwner = this
        viewModel.startActivityForResultEvent.setEventReceiver(this, this)
    }
    public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        viewModel.onResultFromActivity(requestCode, data)
        super.onActivityResult(requestCode, resultCode, data)
    }
}
LoginViewModel.kt:
Enter fullscreen mode Exit fullscreen mode

package com.hms.directory.viewmodel
@SuppressLint("StaticFieldLeak")
class LoginViewModel(application: Application) : AndroidViewModel(application), Observable {
private val context = getApplication().applicationContext
private var mAuthManager: AccountAuthService? = null
private var mAuthParam: AccountAuthParams? = null
val startActivityForResultEvent = LiveMessageEvent()
fun login() {
val intent = Intent(context, OrderActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
context.startActivity(intent)
/* mAuthParam = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
.setIdToken()
.setAccessToken()
.createParams()
mAuthManager = AccountAuthManager.getService(Activity(), mAuthParam)
startActivityForResultEvent.sendEvent {
startActivityForResult(
mAuthManager?.signInIntent,
HMS_SIGN_IN
)
}*/
}
fun onResultFromActivity(requestCode: Int, data: Intent?) {
when (requestCode) {
HMS_SIGN_IN -> {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
onCompleteLogin(authAccountTask)
}
}
}
private fun onCompleteLogin(doneTask: Task) {
if (doneTask.isSuccessful) {
val authAccount = doneTask.result
Log.d("LoginViewModel", "SigIn Success")
context.startActivity(Intent(context, ContactListActivity::class.java))
} else {
Log.d("LoginViewModel", "SigIn Error")
}
}
override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
}
override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) {
}
}

ContactActivity.kt:
Enter fullscreen mode Exit fullscreen mode

public class ContactListActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_list);
// Load contacts from file
Contacts.loadData(this);
// Set up recycler view and fill it with all the contacts
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.contact_list);
recyclerView.setAdapter(new ContactListAdapter(this, Contacts.LIST));
}

LoginFireBaseActivity.java
Enter fullscreen mode Exit fullscreen mode

package com.hms.directory.app.call;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;
import com.google.firebase.database.FirebaseDatabase;
import com.hms.corrierapp.R;
import com.hms.directory.app.call.models.User;
import org.jetbrains.annotations.NotNull;
public class LoginActivity extends AppCompatActivity {
GoogleSignInClient mGoogleSignInClient;
int RC_SIGN_IN = 11;
FirebaseAuth mAuth;
FirebaseDatabase database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login_goole);
mAuth = FirebaseAuth.getInstance();
if (mAuth.getCurrentUser() != null) {
goToNextActivity();
}
database = FirebaseDatabase.getInstance();
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken("1016048264402-439a9aamtpiajbgqeqg24qkum2bb7fmh.apps.googleusercontent.com")
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
findViewById(R.id.loginBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);
//startActivity(new Intent(LoginActivity.this, MainActivity.class));
}
});
}
void goToNextActivity() {
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable @org.jetbrains.annotations.Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
Task task = GoogleSignIn.getSignedInAccountFromIntent(data);
GoogleSignInAccount account = task.getResult();
authWithGoogle(account.getIdToken());
}
}
void authWithGoogle(String idToken) {
AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(@NonNull @notnull Task task) {
if (task.isSuccessful()) {
FirebaseUser user = mAuth.getCurrentUser();
User firebaseUser = new User(user.getUid(), user.getDisplayName(), user.getPhotoUrl().toString(), "Unknown", 500);
database.getReference()
.child("profiles")
.child(user.getUid())
.setValue(firebaseUser).addOnCompleteListener(new OnCompleteListener() {
@Override
public void onComplete(@NonNull @notnull Task task) {
if (task.isSuccessful()) {
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finishAffinity();
} else {
Toast.makeText(LoginActivity.this, task.getException().getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
}
});
//Log.e("profile", user.getPhotoUrl().toString());
} else {
Log.e("err", task.getException().getLocalizedMessage());
}
}
});
}
}



Xml layout DataBinding
To include data binding in the UI, enclose all content with <layout></layout>.

The ViewModel is introduced to the layout in the <data></data> section, as shown. Ensure that the type value points to the specific folder that has the required ViewModel.

App Build Result

​​​​​​​​
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dluosi7wzzik7qfl2m8u.png)


Tips and Tricks

Identity Kit displays the HUAWEI ID registration or sign-in page first. The user can use the functions provided by Identity Kit only after signing in using a registered HUAWEI ID.

Conclusion

In this article, we have learned how to integrate Huawei Identity Kit in Android application. After completely read this article user can easily implement Huawei ID in the Directory App android application using Kotlin.

Thanks for reading this article. Be sure to like and comment to this article, if you found it helpful. It means a lot to me.

References

HMS Docs:

https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/introduction-0000001050048870
Enter fullscreen mode Exit fullscreen mode

Top comments (0)