I'm new on android development, so decided to learn simple login using MVP architectural pattern, in general everything is working fine, as checking user credentials, calling repository...etc.
However, only the implementations of showProgress() & hideProgress() that works in a weird way, for me at least.
Note that the showProgress() only works if the user inter valid credentials.
Thanks.
// Presenter Class
package com.example.mvp.login;
import android.util.Log;
import com.example.mvp.login.LoginContract;
import com.example.mvp.utils.SharedPrefManager;
public class LoginPresenterImpl implements LoginContract.Presenter{
SharedPrefManager sharedPrefManager;
private LoginContract.View view;
private LoginContract.Service service;
public LoginPresenterImpl(LoginContract.View view, LoginContract.Service service) {
this.view = view;
this.service = service;
sharedPrefManager = SharedPrefManager.getInstance(view.getContext());
}
#Override
public void onLoginClicked() {
String username = view.getUsername();
if (username.isEmpty()){
view.showUsernameError();
view.hideProgress();
return;
}
String password = view.getPassword();
if (password.isEmpty()){
view.showPasswordError();
view.hideProgress();
return;
}
view.showProgress(); // this method is called, but doesn't show in the UI Thread
boolean loginSucceeded = service.login(username, password);
if (loginSucceeded){
sharedPrefManager.userLogin(username);
view.navigateHome();
return;
}
view.hideProgress();
view.showLoginError();
}
#Override
public void isUserLoggedIn() {
if(sharedPrefManager.isLoggedIn())
view.navigateHome();
}
}
// View Class
public class LoginActivity extends AppCompatActivity implements LoginContract.View{
private EditText ed_username, ed_password;
private Button login;
private TextView signUp;
private ProgressBar progressBar;
LoginContract.Presenter presenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
initView(this);
presenter = new LoginPresenterImpl(this, new LoignServiceImpl());
presenter.isUserLoggedIn();
login.setOnClickListener(click);
}
View.OnClickListener click = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.login:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
presenter.onLoginClicked();
}
}, 1200);
}
}
};
public void initView(LoginActivity view){
ed_username = view.findViewById(R.id.username);
ed_password = view.findViewById(R.id.password);
login = view.findViewById(R.id.login);
signUp = view.findViewById(R.id.sign_up);
progressBar = view.findViewById(R.id.progressBar);
}
#Override
public String getUsername() {
return ed_username.getText().toString();
}
#Override
public String getPassword() {
return ed_password.getText().toString();
}
#Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
#Override
public void showUsernameError() {
ed_username.setError("Must not be empty");
}
#Override
public void showPasswordError() {
ed_password.setError("Must not be empty");
}
#Override
public void navigateHome() {
Intent intent = new Intent(this, HomeActivity.class);
startActivity(intent);
finish();
}
#Override
public void showLoginError() {
Toast.makeText(this,
"User not Found",
Toast.LENGTH_SHORT).show();
}
#Override
public Context getContext() {
return this;
}
}
Thanks to h4rd4r7c0r3 and Ionut J. Bejan, for highlighting several aspects i wasn't a ware of, in particular Working Thread(UI THREAD) and Another Thread(Background Thread).
Although i don't know yet how to implement them very well, i found way after searching the internet.
The main scenario are:
When the user enter username and password, UI should show indication
(Progress Bar) checking credentialiy of the user, implementing
showProgress().
When the checking is finished, UI should stop the indication.
implementing hideProgress().
An action to be taken based on the result, for example: Navigate to
new Activity or Toast "Wrong Username/Passowrd".
//LoginActivity
#Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
// LoginPresenter
public void onLoginClicked() {
String username = view.getUsername();
if (username.isEmpty()){
view.showUsernameError();
view.hideProgress();
return;
}
String password = view.getPassword();
if (password.isEmpty()){
view.showPasswordError();
view.hideProgress();
return;
}
view.showProgress();
service.login(username,password, this);
}
#Override
public void isUserLoggedIn() {
if(sharedPrefManager.isLoggedIn())
view.navigateHome();
}
// implementing onFinished from FinishedListiner interface, to capture the result
#Override
public void onFinished(boolean bool) {
view.hideProgress();
if (bool){
sharedPrefManager.userLogin(view.getUsername());
view.navigateHome();
return;
}
view.showLoginError();
}
// Service, which will connect to the datasource
public class LoginServiceImpl implements LoginContract.Service {
UserRepository userRepository;
#Override
public void login(final String username, final String password, final FinishedListiner listener) {
userRepository = UserRepositoryImpl.getInstance();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// The method which will be used in the presenter class.
listener.onFinished(userRepository.checkUser(username, password));
}
}, 1200);
}
Try this below snippet :
Step 1:- Create BaseActivity extend to AppCompactActivity
Step 2:-Setting BaseActivity as per your requirement
Step 3:-Create Instance of your Progress Dialog
Step 4:-Create function showProgress()
Like:-
private fun showProgress(){
if(!progress.isShowing){
progress.show()
}
}
Step 5:- Create function HideProgress()
Like:-
private fun hideProgress(){
if(progress.isShowing){
progress.dismiss()
}
}
And use as per your requirement.
Your View just run presenter on another thread. See your Handler. Then it update the view and can not access to the UI. To fix this, just make sure your showProgress() is doing work on UI thread.
runOnUiThread(new Runnable() {
public void run() {
//show your proress here.
}
});
Related
I have a progress dialog that shows how many files are left for uploading in my Async Task and the user can dismiss this dialog if he wants to. However I want to have a button that will be able to show again that progress dialog at its current stage and I don't know how to do that since you I can't just create a function in the Async Task and call it from a different activity. Any thoughts?
You can make a singleton class to handle the Async Task progress which holds only one listener (the Activity who wants to listen for the progress of your AsyncTask).
Your Singleton class can be like below:
public class ProgressDialogUtil {
public interface ProgressDialogUtilListener{
void showProgressDialog();
void dismissProgressDialog();
void updateProgressDialog(int value);
void setProgressDialogMessage(String message);
}
private ProgressDialogUtilListener listener;
private static ProgressDialogUtil mInstance;
public static ProgressDialogUtil getInstance() {
if (mInstance == null) {
synchronized (ProgressDialogUtil.class) {
if (mInstance == null) {
mInstance = new ProgressDialogUtil();
}
}
}
return mInstance;
}
public void setListener(ProgressDialogUtilListener listener) {
this.listener = listener;
}
public void showProgressDialog(){
if(listener!=null)
listener.showProgressDialog();
}
public void dismissProgressDialog(){
if(listener!=null)
listener.dismissProgressDialog();
}
public void updateProgressDialog(int value){
setProgressDialogMessage("Files Downloaded: "+ value);
if(listener!=null)
listener.updateProgressDialog(value);
}
public void setProgressDialogMessage(String message){
if(listener!=null)
listener.setProgressDialogMessage(message);
}
}
Then you can use this Singleton class (ProgressDialogUtil) in your AsyncTask like below to inform for any update occurred:
public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
public final ProgressDialogUtil progressDialogUtil;
public MyAsyncTask(ProgressDialogUtil progressDialogUtil){
this.progressDialogUtil = progressDialogUtil;
}
#MainThread
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialogUtil.setProgressDialogMessage("Start Download files..");
progressDialogUtil.showProgressDialog();
}
#WorkerThread
#Override
protected Boolean doInBackground(Void... params) {
//download your files here in the Background Thread...
//below is a sample loop
for (int i=0; i <= 50; i++) {
try {
Thread.sleep(1000);
publishProgress(i);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
return true;
}
#MainThread
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressDialogUtil.updateProgressDialog(values[0]);
}
#MainThread
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
progressDialogUtil.setProgressDialogMessage("Finished Download!");
progressDialogUtil.dismissProgressDialog();
}
}
Then in your first Activity where you start the AsyncTask you can create a new instance of your Progress Dialog and set a listener ProgressDialogUtilListener to listen for any AsyncTask progress to show/hide/update the Progress Dialog like below:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
{
#Override
public void showProgressDialog() {
if (!pd.isShowing())
pd.show();
}
#Override
public void dismissProgressDialog() {
if (pd.isShowing())
pd.dismiss();
}
#Override
public void updateProgressDialog(int value) {
pd.setProgress(value);
}
#Override
public void setProgressDialogMessage(String message) {
pd.setMessage(message);
}
});
new MyAsyncTask(progressDialogUtil).execute();
Finally when you navigate to a new Activity you can use the same Singleton Instance ProgressDialogUtil and change the listener to the new Activity now all AsyncTask events will be handled to the new Activity and the dialog can be opened/closed via a button through this singleton class like below:
ProgressDialog pd = new ProgressDialog(this);
ProgressDialogUtil progressDialogUtil = ProgressDialogUtil.getInstance();
progressDialogUtil.setListener(new ProgressDialogUtil.ProgressDialogUtilListener()
{
#Override
public void showProgressDialog() {
if (!pd.isShowing())
pd.show();
}
#Override
public void dismissProgressDialog() {
if (pd.isShowing())
pd.dismiss();
}
#Override
public void updateProgressDialog(int value) {
pd.setProgress(value);
}
#Override
public void setProgressDialogMessage(String message) {
pd.setMessage(message);
}
});
//Show Progress Dialog from a Button Click
showButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressDialogUtil.showProgressDialog();
}
});
//Dismiss Progress Dialog from a Button Click
dismissButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
progressDialogUtil.dismissProgressDialog();
}
});
You can have a Live data in any singleton class like below to share the progress between activities.
object ProgressHelper {
val progress = MutableLiveData<Int>()
}
Then update the progress values from the AsyncTask like below:
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
ProgressHelper.progress.value = 100
}
In your activity you can observe the progress like below:
ProgressHelper.progress.observe(this, Observer {
val progress = it
})
I am learning MVP design for the Android , I am new to it so need your valuable time . I went to the basics of the MVP how it work , Now i got stuck so need your help , I have to post the data to the server , when i hard code the value in presenter then i get the response correct but i need the data that is in the LoginActivity view when user press then that value should pass to the presenter and presenter pass that value to the Retrofit and bring back the result . Here is my try :
My LoginActvity:
public class LoginActivity extends BaseActivity implements LoginView {
#BindView(R.id.company_name)
protected EditText companyName_et;
#BindView(R.id.email)
protected EditText email_et;
#BindView(R.id.password)
protected EditText password_et;
#BindView(R.id.submit)
protected Button submit_btn;
#Inject
LoginPresenter loginPresenter;
#Override
protected int getContentView() {
return R.layout.login_activity;
}
#Override
protected void onViewReady(Bundle savedInstanceState, Intent intent) {
super.onViewReady(savedInstanceState, intent);
submit_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String company=companyName_et.getText().toString();
String username=email_et.getText().toString();
String password=password_et.getText().toString();
/*
I have to put the above String data
to my model class then i have to post the data to the server
*/
loginPresenter.passLoginDataToServer();
}
});
}
#Override
public void onError(String s) {
Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
}
#Override
public void onSuccess(String s) {
}
#Override
public void onResponse(Login login) {
Log.e("-----",""+login.getUserId());
}
#Override
protected void resolveDaggerDependency() {
DaggerLoginComponent.builder().applicationComponent(getApplicationComponent()).loginModule(new LoginModule(this)).build().inject(this);
}
}
Here is Login Presenter :
public class LoginPresenter extends BasePresenter<LoginView> implements Observer<Login>{
#Inject
CreateApiService createApiService;
#Inject
public LoginPresenter(){};
public void passLoginDataToServer(){
/*
when i hard code the data , i get the successful response.Like :
String user="raj";
String check="true";
Map<String,String> headers=new HashMap();
headers,put("xyz","pqr");
Login loginObject = new Login("xyzs", "pqr","Qtch","mvp");
*/
/*
But I need the data here from my LoginActivity ? Dunno how to pass the data from LoginActivity to presenter
*/
Observable<Login> loginObservable=createApiService.loginUser(user, check, headers, loginObject);
subscribeToLogin(loginObservable,this);
}
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(Login login) {
getmView().onResponse(login);
}
#Override
public void onError(Throwable e) {
getmView().onError("Error "+e);
Log.e("---",""+e);
}
#Override
public void onComplete() {
getmView().onSuccess("Successfully Loaded");
}
}
Here is My Interface :
public interface LoginView extends BaseView {
void onError(String s);
void onSuccess(String s);
void onResponse(Login login);
}
Could you add the parameters to the method?
In your activity:
#Override public void onClick(View view) {
String company=companyName_et.getText().toString();
String username=email_et.getText().toString();
String password=password_et.getText().toString();
loginPresenter.passLoginDataToServer(compay, username, password);
}
In your presenter:
public void passLoginDataToServer(String company, String username, String password){
// Now create your request from the dynamic parameters
Observable<Login> loginObservable=createApiService.loginUser(username, check, headers, loginObject);
subscribeToLogin(loginObservable,this);
}
I hope you understand the errors in my coding. I want to retrieve value from function "ambilKey()" to get the value for "hasilKey". "hasilKey" is the node of my firebase database structure.
MyPictureDatabaseFirebase:
MyPictureResultLog:
value -KkonCYNZV6BX5BmWUI not saved to variable "hasilKey". So, this code doesn't work: dbAmbilDataProduk=FirebaseDatabase.getInstance().getReference().child("DataBisnis").child(hasilKey).child("DataProduk").
public class IbuActivity extends AppCompatActivity {
private Fireb][1]aseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference mCekBisnis_Id;
private String nilaiBisnis="error";
private String hasilKey="error";
private RecyclerView mProdukList;
private DatabaseReference dbAmbilKeyPengguna;
private DatabaseReference dbAmbilDataProduk;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ibu);
Log.i("Aktivitas :","OnCreate");
mAuth=FirebaseAuth.getInstance();
cekAkunBisnis();
//Retrieve Value hasilKey is my problem
ambilKey();
//Check Value
Log.i("Result=",hasilKey);
//Not working function ambilkey() ?????
dbAmbilDataProduk=FirebaseDatabase.getInstance().getReference().child("DataBisnis").child(hasilKey).child("DataProduk");
mProdukList=(RecyclerView) findViewById(R.id.ibuRvProduk);
mProdukList.setHasFixedSize(true);
mProdukList.setLayoutManager(new LinearLayoutManager(this));
}
private void ambilKey() {
dbAmbilKeyPengguna=FirebaseDatabase.getInstance().getReference().child("DataPengguna").child(mAuth.getCurrentUser().getUid()).child("BisnisId");
dbAmbilKeyPengguna.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
hasilKey=dataSnapshot.getValue(String.class);
Log.i("ResultKeyAmbilKey=",hasilKey);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.i("Pesan","DatabaseError");
}
});
}
#Override
public void onStart() {
super.onStart();
FirebaseRecyclerAdapter<AmbilDataProduk,ProdukViewHolder> firebaseRecyclerAdapter=new FirebaseRecyclerAdapter<AmbilDataProduk, ProdukViewHolder>(
AmbilDataProduk.class,
R.layout.listprodukrow,
ProdukViewHolder.class,
dbAmbilDataProduk
) {
#Override
protected void populateViewHolder(ProdukViewHolder viewHolder, AmbilDataProduk model, int position) {
viewHolder.setNamaProduk(model.getNamaProduk());
viewHolder.setHargaProduk(model.getHargaProduk());
viewHolder.setFotoProduk(getApplicationContext(),model.getFotoProduk());
}
};
mProdukList.setAdapter(firebaseRecyclerAdapter);
}
public static class ProdukViewHolder extends RecyclerView.ViewHolder{
View view;
public ProdukViewHolder(View itemView) {
super(itemView);
view=itemView;
}
public void setNamaProduk(String namaProduk){
TextView buNamaProduk=(TextView) view.findViewById(R.id.prowTvNama);
buNamaProduk.setText(namaProduk);
}
public void setHargaProduk(String hargaProduk) {
TextView kelolaHargaProduk=(TextView) view.findViewById(R.id.prowTvHarga);
kelolaHargaProduk.setText("Harga : Rp."+hargaProduk);
}
public void setFotoProduk(final Context ctx, final String fotoProduk){
final ImageView imageViewFotoProduk=(ImageView) view.findViewById(R.id.prowIvFoto);
//Picasso.with(ctx).load(fotoProduk).into(imageViewFotoProduk);
Picasso.with(ctx).load(fotoProduk).networkPolicy(NetworkPolicy.OFFLINE).into(imageViewFotoProduk, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(ctx).load(fotoProduk).into(imageViewFotoProduk);
}
});
}
}
//Cek Akun sudah Login Jika sudah login apakah sudah terdaftar / punya bisnis
private void cekAkunBisnis() {
//CekAkunLogin
if(mAuth.getCurrentUser()!=null){
mCekBisnis_Id= FirebaseDatabase.getInstance().getReference().child("DataPengguna").child(mAuth.getCurrentUser().getUid()).child("BisnisId");
mCekBisnis_Id.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
nilaiBisnis=dataSnapshot.getValue(String.class);
//Cek sudah punya bisnis belum?
if(!nilaiBisnis.equals("belumada")){
//Sudah ada
}
else if(nilaiBisnis.equals("error")){
}
else{
//Belum ada
Intent bisnisIntent=new Intent(IbuActivity.this, BisnisActivity.class);
//Data activitynya dilupakan
bisnisIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(bisnisIntent);
Toast.makeText(IbuActivity.this, "Selamat Datang. Silahkan Isi nama Bisnis Anda", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(IbuActivity.this, "Database Error!!!", Toast.LENGTH_SHORT).show();
}
});
}
else{
//User tidak ada
Intent loginRegister=new Intent(IbuActivity.this, LoginRegister.class);
loginRegister.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(loginRegister);
}
}
//Membuat menu
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_tambahproduk, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()==R.id.actionTambahProduk){
startActivity(new Intent(IbuActivity.this,KelolaProduk.class));
}
return super.onOptionsItemSelected(item);
}
}
You cannot use that variable outside the onDataChange() method in the way you do. This is happening because onDataChange() is called asynchronously. This means that your method is executed before onDataChange has been called. That's why is not displaying the correct value. So in order to use that variable, you need to use it inside the onDataChange() method.
For other approach, please visit this post and this post. You'll understand for sure better how things works.
I take reference from official website https://quickblox.com/developers/Android#Download_Android_SDK
gradle compile succeed:
repositories {
maven {
url "https://github.com/QuickBlox/quickblox-android-sdk-releases/raw/master/"
}
}
dependencies {
compile "com.quickblox:quickblox-android-sdk-core:2.5.1#aar"
compile("com.quickblox:quickblox-android-sdk-chat:2.5.1#aar") {
transitive=true
}
}
then i use the code first:
I had the APP_ID...etc
QBSettings.getInstance().init(getApplicationContext(), APP_ID, AUTH_KEY, AUTH_SECRET);
QBSettings.getInstance().setAccountKey(ACCOUNT_KEY);
Second step :
I reference Guide: Getting Started with Chat API https://quickblox.com/developers/Android_XMPP_Chat_Sample#Guide:_Getting_Started_with_Chat_API
//Prepare chat service
QBChatService.setDebugEnabled(true); // enable chat logging
QBChatService.setDefaultPacketReplyTimeout(10000);//set reply timeout in milliseconds for connection's packet.
//Can be used for events like login, join to dialog to increase waiting response time from server if network is slow.
//configure chat socket
QBChatService.ConfigurationBuilder chatServiceConfigurationBuilder = new QBChatService.ConfigurationBuilder();
chatServiceConfigurationBuilder.setSocketTimeout(60); //Sets chat socket's read timeout in seconds
chatServiceConfigurationBuilder.setKeepAlive(true); //Sets connection socket's keepAlive option.
chatServiceConfigurationBuilder.setUseTls(true); //Sets the TLS security mode used when making the connection. By default TLS is disabled.
QBChatService.setConfigurationBuilder(chatServiceConfigurationBuilder);
It has a issue that i can't import QBChatService.ConfigurationBuilder
so i try to change gradle to compile("com.quickblox:quickblox-android-sdk-chat:2.6.1")
now QBChatService.ConfigurationBuilder can be import
Third step:
I take the official step use the code:
// Initialise Chat service
final QBChatService chatService = QBChatService.getInstance();
final QBUser user = new QBUser("garrysantos", "garrysantospass");
QBAuth.createSession(user, new QBEntityCallback<QBSession>() {
#Override
public void onSuccess(QBSession qbSession, Bundle bundle) {
// success, login to chat
user.setId(qbSession.getUserId());
chatService.login(user, new QBEntityCallback() {
#Override
public void onSuccess(Object o, Bundle bundle) {
}
#Override
public void onError(QBResponseException e) {
}
});
}
#Override
public void onError(QBResponseException e) {
}
});
//To handle different connection states use ConnectionListener:
ConnectionListener connectionListener = new ConnectionListener() {
#Override
public void connected(XMPPConnection xmppConnection) {
}
#Override
public void authenticated(XMPPConnection xmppConnection, boolean b) {
}
#Override
public void connectionClosed() {
}
#Override
public void connectionClosedOnError(Exception e) {
// connection closed on error. It will be established soon
}
#Override
public void reconnectionSuccessful() {
}
#Override
public void reconnectingIn(int i) {
}
#Override
public void reconnectionFailed(Exception e) {
}
};
QBChatService.getInstance().addConnectionListener(connectionListener);
//logOut
boolean isLoggedIn = chatService.isLoggedIn();
if (!isLoggedIn) {
return;
}
chatService.logout(new QBEntityCallback<Void>() {
#Override
public void onSuccess(Void aVoid, Bundle bundle) {
//success
chatService.destroy();
}
#Override
public void onError(QBResponseException e) {
}
});
//By default Android SDK reconnects automatically when connection to server is lost.
//But there is a way to disable this and then manage this manually:
QBChatService.getInstance().setReconnectionAllowed(false);
when i use the step about QBChatDialog , it can't be import again....
ArrayList<Integer> occupantIdsList = new ArrayList<Integer>();
occupantIdsList.add(34);
occupantIdsList.add(17);
QBChatDialog dialog = new QBChatDialog();
dialog.setName("Chat with Garry and John");
dialog.setPhoto("1786");
dialog.setType(QBDialogType.GROUP);
dialog.setOccupantsIds(occupantIdsList);
//or just use DialogUtils
//for creating PRIVATE dialog
//QBChatDialog dialog = DialogUtils.buildPrivateDialog(recipientId);
//for creating GROUP dialog
QBChatDialog dialog = DialogUtils.buildDialog("Chat with Garry and John", QBDialogType.GROUP, occupantIdsList);
QBRestChatService.createChatDialog(dialog).performAsync(new QBEntityCallback<QBChatDialog>() {
#Override
public void onSuccess(QBChatDialog result, Bundle params) {
}
#Override
public void onError(QBResponseException responseException) {
}
});
so i try to change gradle compile compile("com.quickblox:quickblox-android-sdk-chat:3.3.0")
now QBChatDialog can be imported.
but it has another issues...
Can't not resolve symbol 'QBSettings' and 'QBSession'
I'm angry now , are you kidding me ?
Why the official step cheat me step by step ?
I'm tired... what should i do ?
Somebody can save me please , any help would be appreciated !
According #Jagapathi kindly responding , i update my code , the next issue is that i can't log in
My toast shows Login error when i click the login button:
private void setupQuickBlox() {
QBSettings.getInstance().init(getApplicationContext(), APP_ID, AUTH_KEY, AUTH_SECRET);
QBSettings.getInstance().setAccountKey(ACCOUNT_KEY);
QBSettings.getInstance().setAutoCreateSession(true);
//login to quickblox
String enterAccount = editAccount.getText().toString();
String enterPassword = editPassword.getText().toString();
Log.d(TAG,enterAccount);
Log.d(TAG,enterPassword);
final QBUser user = new QBUser(enterAccount, enterPassword);
//login
QBUsers.signIn(user).performAsync(new QBEntityCallback<QBUser>() {
#Override
public void onSuccess(QBUser qbUser, Bundle bundle) {
SharedPreferences.Editor s = getSharedPreferences("QBid", 0).edit();
s.putString("id", user.getId().toString());
s.apply();
Log.d(TAG,user.getId().toString());
Toast.makeText(MainActivity.this, "Login success with quickblox", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(QBResponseException e) {
Toast.makeText(MainActivity.this, "Login error", Toast.LENGTH_SHORT).show();
}
});
}
the code is under my onCreat , so it shows Login error when i satrt the app of course , but when i enter account and password , it still shows Login error , why? I check the log , i can see the account and password that i typed , but i can't see user.getId().toString() on my log , what step is wrong ?
i check the account is correct:
Here is my key:
static final String APP_ID = "50427";
static final String AUTH_KEY = "naMGFKMshdLC3s4";
static final String AUTH_SECRET = "GP8ey4GsQXt2TGu";
static final String ACCOUNT_KEY = "dHYgix3we3bxxsvMqyuR";
Here is my test Account key:
My button onClcik:
buttonLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setupQuickBlox();
}
});
Here is my log:
I can guide you with Quickblox I am in same position when I started using quickblox.
step 1:-
compile 'com.quickblox:quickblox-android-sdk-core:3.3.0#aar'
compile("com.quickblox:quickblox-android-sdk-chat:3.3.0#aar") {
transitive = true
}
This is for latest version of quickblox. So don't use old versions .
step 2:-
This is my SetUp Quickblox function you don't forgot to use app_id Auth_key auth_secret and account_key
private void SetupQuickBlox() {
QBSettings.getInstance().init(getApplicationContext(), APP_ID, AUTH_KEY, AUTH_SECRET);
QBSettings.getInstance().setAccountKey(ACCOUNT_KEY);
QBSettings.getInstance().setAutoCreateSession(true);
//login to quickblog for
final QBUser user=new QBUser("USER_NAME OF USER","PASSWORD OF USER");
// Login
QBUsers.signIn(user).performAsync(new QBEntityCallback<QBUser>() {
#Override
public void onSuccess(QBUser user, Bundle args) {
// success
SharedPreferences.Editor s=getSharedPreferences("QBid",0).edit();
s.putString("id",user.getId().toString());
s.apply();
Toast.makeText(HomeActivity.this, "Login succes with quickblox", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(QBResponseException error) {
// error
}
});
}
step:- 3
You are all done Login with quickblox is successful so you can now request DIALOGS or CREATE DIALOg Sessions are automatically created in latest version.
Create New Dialog
private void NewMessage() {
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
QBChatDialog dialog = DialogUtils.buildPrivateDialog("USER_ID of other user");
dialog.setName("tester1");
QBRestChatService.createChatDialog(dialog).performAsync(new QBEntityCallback<QBChatDialog>() {
#Override
public void onSuccess(QBChatDialog result, Bundle params) {
}
#Override
public void onError(QBResponseException responseException) {
}
});
}
});
}
Request List Of Dialog Of Logged In User
I Used ListView And Dialogs result will be in array list which contains LIST of QBCHATDIALOG
private void receiveChatList() {
QBRequestGetBuilder requestBuilder = new QBRequestGetBuilder();
requestBuilder.setLimit(100);
QBRestChatService.getChatDialogs(null, requestBuilder).performAsync(
new QBEntityCallback<ArrayList<QBChatDialog>>() {
#Override
public void onSuccess(final ArrayList<QBChatDialog> result, Bundle params) {
int totalEntries = params.getInt("total_entries");
Log.wtf("chat",""+result);
TrumeMsgAdapter adapter=new TrumeMsgAdapter(TrueMeMessagesActivity.this,result);
chatlistView.setAdapter(adapter);
chatlistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startActivity(new Intent(TrueMeMessagesActivity.this,ChatingActivity.class).putExtra("dialog",result.get(position)));
}
});
}
#Override
public void onError(QBResponseException responseException) {
}
});
}
My Adapter Code
public class TrumeMsgAdapter extends BaseAdapter {
private ArrayList<QBChatDialog> chatlist;
private Context context;
public TrumeMsgAdapter(Context c,ArrayList<QBChatDialog> chatlist){
this.chatlist=chatlist;
this.context=c;
}
#Override
public int getCount() {
return chatlist.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View List;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
List = inflater.inflate(R.layout.trume_msg_adapter, null);
TextView username=(TextView) List.findViewById(R.id.UserName);
TextView lastmessage=(TextView)List.findViewById(R.id.lastmessage);
username.setText(chatlist.get(position).getName());
lastmessage.setText(chatlist.get(position).getLastMessage());
} else {
List = convertView;
TextView username=(TextView) List.findViewById(R.id.UserName);
TextView lastmessage=(TextView)List.findViewById(R.id.lastmessage);
username.setText(chatlist.get(position).getName());
lastmessage.setText(chatlist.get(position).getLastMessage());
}
return List;
}
}
i'm using facebook runner to apply some facebook api tesk.
i want to check if i got a JSON object with data or and error message so i'm checking the "message" field to check if it's null.
if it is not null and i have a massage, i want to display the message and exit the application.
this is my code in my activity:
public class Loader extends Activity implements FacebookConnectionListener, ServerDataListener {
private TextView loaderStatus;
private Facebook facebook;
private AsyncFacebookRunner facebookRunner;
private FacebookConnection facebookConnection;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loader);
facebook = new Facebook(facebookAppId);
facebookRunner = new AsyncFacebookRunner(facebook);
facebookConnection = new FacebookConnection(this, 1);
facebookRunner.request("me",facebookConnection);
}
#Override
public void onFacebookResponse(final String response , int step) {
final JSONObject facebookResults = convertToJSON(response);
final Context thisContext = (Context) getBaseContext();
String id = "", name = "", gender = "", homeTown = "";
Drawable profilePicture = null;
if (step == 1) {
if (facebookResults.isNull("message")) {
try {
id = facebookResults.getString("id");
name = facebookResults.getString("name");
gender = facebookResults.getString("gender");
JSONObject homeTownObject = (JSONObject) facebookResults.get("hometown");
homeTown = homeTownObject.getString("name");
profilePicture = getProfilePicture(id);
} catch (JSONException e) {
alert("Facebook", e.toString(), "Ok", thisContext);
}
facebookCurrentUser = new FacebookCurrentUser(id, name, gender);
facebookCurrentUser.setHomeTown(homeTown);
facebookCurrentUser.setProfilePicture(profilePicture);
app.setFacebookCurrentUser(facebookCurrentUser);
facebookConnection = new FacebookConnection(this, 2);
this.runOnUiThread(new Runnable() {
public void run() {
loaderStatus.setText("Getting friends details");
}
});
}
else {
this.runOnUiThread(new Runnable() {
public void run() {
alert("Facebook", "Can't get user details! Please try again", "Ok", thisContext);
}
});
}
}
public void alert (String title, String message, String ok, Context listener)
{
AlertDialog.Builder alert = new AlertDialog.Builder(listener);
alert.setMessage(message);
alert.setTitle(title);
alert.setPositiveButton(ok, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
}
this is FacebookConnection class:
public class FacebookConnection implements RequestListener {
private FacebookConnectionListener listener;
private int step;
public FacebookConnection (FacebookConnectionListener listener, int step) {
this.listener = listener;
this.step = step;
}
public void updateFacebookListener(String response) {
listener.onFacebookResponse(response, step);
}
#Override
public void onComplete(String response, Object state) {
updateFacebookListener(response);
}
#Override
public void onIOException(IOException e, Object state) { }
#Override
public void onFileNotFoundException(FileNotFoundException e, Object state) { }
#Override
public void onMalformedURLException(MalformedURLException e, Object state) { }
#Override
public void onFacebookError(FacebookError e, Object state) { }
}
the FacebookConnectionListener interface:
public interface FacebookConnectionListener {
public void onFacebookResponse(String response, int step);
}
my alerts keep giving me the :
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
and i can't understand why.. help ?
Well, try this:
public void alert (String title, String message, String ok) {
this.runOnUiThread(new Runnable() {
public void run() {
AlertDialog alert = new AlertDialog.Builder(Loader.this).create();
alert.setMessage(message);
alert.setTitle(title);
alert.setPositiveButton(ok, new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alert.show();
}
});
}
Instead of what you have now, and when you call it, just call it like any other method:
this.alert("Facebook", "Can't get user details! Please try again", "Ok")
I'm not exactly sure where it goes wrong, it even might have to do with you forgetting the create() part when constructing the dialog.
Hope this will sort things for you.
The reason it is appearing is because you are trying to update Ui from a different thread. As this is a partial code, I can suggest you changing your code to
MyActivity.this.runOnUiThread(new Runnable() {
public void run() {
loaderStatus.setText("Getting friends details");
}
});
where MyActivity is your Activity's name.
the easy way:
u can publishProgress(something)
and process the publishing, to show your alert :D