Saripaar Validation library throws No rules found error - android

I'm trying to use Saripaar Validation on my project, but it's throwing the following error:
java.lang.IllegalStateException: No rules found. You must have at
least one rule to validate. If you are using custom annotations, make
sure that you have registered them using the 'Validator.register()'
method.
My architecture separates the responsibility for handling the view into a class, for example for LoginActivity I have LoginView, which is where I handle my view logic like ButterKnife injection, event listening, etc. In this class I have my annotated fields.My LoginView looks like this:
import android.content.res.ColorStateList;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.ImageViewCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatEditText;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.mobsandgeeks.saripaar.ValidationError;
import com.mobsandgeeks.saripaar.Validator;
import com.mobsandgeeks.saripaar.annotation.Email;
import com.mobsandgeeks.saripaar.annotation.NotEmpty;
import com.mobsandgeeks.saripaar.annotation.Password;
import com.serti.android.feenicia.validatortest.R;
import com.serti.android.feenicia.validatortest.screen.login.LoginActivity;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import rx.Observable;
import rx.subjects.PublishSubject;
public class LoginView implements Validator.ValidationListener {
public static final String LOGIN_ACTION = "LOGIN";
#BindView(R.id.login_button)
Button loginButton;
#BindView(R.id.username_edittext)
#NotEmpty
#Email
AppCompatEditText usernameEditText;
#BindView(R.id.password_edittext)
#Password(min = 8, scheme = Password.Scheme.ALPHA_NUMERIC_MIXED_CASE_SYMBOLS)
AppCompatEditText passwordEditText;
#BindView(R.id.eye_imageview)
ImageView eyeImageView;
#BindView(R.id.loading_progressbar)
ProgressBar loadingProgressBar;
private boolean passwordIsVisible;
private AlertDialog confirmPaymentDialog;
private LoginActivity context;
private View rootView;
private PublishSubject<String> clickSubject = PublishSubject.create();
Validator validator;
public LoginView(LoginActivity context){
this.context = context;
FrameLayout parent = new FrameLayout(context);
parent.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
rootView = LayoutInflater.from(context).inflate(R.layout.activity_login, parent, true);
ButterKnife.bind(this, rootView);
validator = new Validator(context);
validator.setValidationListener(this);
eyeImageView.setOnClickListener(v -> handleClick(v.getId()));
loginButton.setOnClickListener(v -> handleClick(v.getId()));
passwordIsVisible = false;
}
#Override
public void onValidationSucceeded() {
String action = null;
Snackbar.make(rootView, "Validated", Snackbar.LENGTH_LONG).show();
loginButton.setVisibility(View.GONE);
loadingProgressBar.setVisibility(View.VISIBLE);
action = LOGIN_ACTION;
if(action != null){
clickSubject.onNext(action);
}
}
#Override
public void onValidationFailed(List<ValidationError> errors) {
for(ValidationError error : errors){
View view = error.getView();
String message = error.getCollatedErrorMessage(context);
if(view instanceof AppCompatEditText){
((AppCompatEditText) view).setError(message);
} else {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
}
}
}
public String getUserName(){
return usernameEditText.getText().toString();
}
public String getPassword(){
return passwordEditText.getText().toString();
}
private void handleClick(int id){
String action = null;
switch (id){
case R.id.login_button:
validator.validate();
break;
case R.id.eye_imageview:
togglePasswordVisibility();
}
}
private void togglePasswordVisibility(){
int color = 0;
if(passwordIsVisible){
passwordEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
// eyeImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.eye_white));
color = ContextCompat.getColor(context, R.color.dark_blue_button);
ImageViewCompat.setImageTintList(eyeImageView, ColorStateList.valueOf(color));
}else{
passwordEditText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
// eyeImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.eye_white));
color = ContextCompat.getColor(context, R.color.dark_gray);
}
ImageViewCompat.setImageTintList(eyeImageView, ColorStateList.valueOf(color));
passwordIsVisible = !passwordIsVisible;
passwordEditText.setSelection(passwordEditText.getText().length());
}
private void showIncompleteCredentialsMessage() {
Snackbar.make(loginButton, context.getText(R.string.incomplete_credentials_title), Snackbar.LENGTH_LONG).show();
}
public View getView(){
return rootView;
}
public Observable<String> observeClicks(){
return clickSubject;
}
public void openMainScreen(){
context.startMainActivity();
}
public void openSearchTicketsScreen() {
context.startSearchTicketsActivity();
}
public void showWrongCredentialsMessage() {
loginButton.setVisibility(View.VISIBLE);
loadingProgressBar.setVisibility(View.GONE);
Snackbar.make(loginButton, context.getText(R.string.wrong_credentials_title), Snackbar.LENGTH_LONG).show();
}
public void setContext(LoginActivity context) {
this.context = context;
}
}
From what I'm guessing, the library is trying to find these fields on my Activity, and since they're not there, then it's throwing this error.
Is there a way use this library accordingly to the architecture I'm handling?

use validator = new Validator(this) in place of validator = new Validator(context);

Related

How to use a ViewModel outside of onCreate()?

I have an Activity with a RecyclerView which display Livedata from a room database.
My aim is to start a new Activity with more data from the room database when the user is clicking on the corresponding item in the RecyclerView.
For that I overwrote the onClick() method in the adapter of the RecylcerView. Each object of the RecyclerView has a Id, I need that Id to get the corresponding data from the database. So I passed the Id from the Adapter to the Activity.
To search an element by Id in the database that I need the ViewModel object in the MainAcitivty. It is initialized in the onCreate() of the Activity. The method I called in the Adapter is outside the onCreate() and I get a null object reference exception when I try to use it.
How can I use the ViewModel outside of the onCreate() method of the Activity? Or is there another way to search for the element in the database?
Thank you!
The Adapter class:
In the onClick() method is the relevant part.
package com.example.fillmyplate.activities;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.fillmyplate.R;
import com.example.fillmyplate.entitys.Recipe;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class RecipeAdapter extends RecyclerView.Adapter<RecipeAdapter.RecipeViewHolder> {
private static final String TAG = "RecipeAdapter";
private List<Recipe> mRecipes = new ArrayList<>();
private LayoutInflater mInflater;
private Context mContext;
private MainActivity mainActivity = new MainActivity();
private static int backGroundIndex = 0;
class RecipeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView recipeTitleItemView;
ImageView imageView;
public RecipeViewHolder(View itemView) {
super(itemView);
recipeTitleItemView = itemView.findViewById(R.id.name);
imageView = itemView.findViewById(R.id.card_image_view);
Log.d(TAG, "RecipeViewHolder: index " + backGroundIndex);
if (backGroundIndex == 0) {
imageView.setImageResource(R.drawable.background_green);
backGroundIndex++;
} else if (backGroundIndex == 1 ) {
imageView.setImageResource(R.drawable.background_red);
backGroundIndex++;
} else if (backGroundIndex == 2 ) {
imageView.setImageResource(R.drawable.background_blue);
backGroundIndex = 0;
}
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
// This should be the mistake.
mainActivity.startKnownRecipeActivity(position);
}
}
public RecipeAdapter(Context context) {
mInflater = LayoutInflater.from(context);
this.mContext = context;
}
#NonNull
#Override
public RecipeAdapter.RecipeViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// Inflate an item view
View mRecipeTitleView = mInflater.inflate(
R.layout.recipe_list_row, parent, false);
return new RecipeViewHolder(mRecipeTitleView);
}
// Get data into the corrsponding views
#Override
public void onBindViewHolder(RecipeAdapter.RecipeViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: " + position);
Recipe currentRecipe = mRecipes.get(position);
Log.d(TAG, "onBindViewHolder: setText " + currentRecipe);
holder.recipeTitleItemView.setText(currentRecipe.getTitle());
}
#Override
public int getItemCount() {
return mRecipes.size();
}
public void setRecipes(List<Recipe> recipes) {
this.mRecipes = recipes;
Log.d(TAG, "setRecipes: notifydataChanged" );
notifyDataSetChanged();
}
}
MainActivity:
package com.example.fillmyplate.activities;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.media.Image;
import android.os.Build;
import android.os.Bundle;
import com.example.fillmyplate.R;
import com.example.fillmyplate.entitys.Recipe;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.cardview.widget.CardView;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainAcitivity";
private static final int NEW_RECIPE_ACTIVITY_REQUEST_CODE = 1;
private RecyclerView mRecyclerView;
private RecipeViewModel mRecipeViewmodel;
private RecyclerView.LayoutManager layoutManager;
//private final List<String> mTitleList = new LinkedList<>();
//NEU for adapter
private List<String> recipeDataList = new ArrayList<>();
RecipeRoomDatabase db;
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// RECYCLER VIEW STUFF
mRecyclerView = findViewById(R.id.recycler_view1);
mRecyclerView.setHasFixedSize(true);
// user linerar layout manager
layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
// specify an adapter
final RecipeAdapter recipeAdapter = new RecipeAdapter(this);
//mAdapter = new RecipeAdapter(this, mTitleList);
mRecyclerView.setAdapter(recipeAdapter);
mRecipeViewmodel = ViewModelProviders.of(this).get(RecipeViewModel.class);
mRecipeViewmodel.getAllRecipes().observe(this, new Observer<List<Recipe>>() {
#Override
public void onChanged(List<Recipe> recipes) {
Log.d(TAG, "onChanged: " + recipes.toString());
for (Recipe rec : recipes) {
Log.d(TAG, "onChanged: " + rec.getTitle());
Log.d(TAG, "onChanged: recipe id " + rec.getUid());
}
recipeAdapter.setRecipes(recipes);
}
});
// DB
db = Room.databaseBuilder(getApplicationContext(), RecipeRoomDatabase.class, "appdb").build();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AddRecipeActivity.class);
startActivityForResult(intent, NEW_RECIPE_ACTIVITY_REQUEST_CODE);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: ");
if (requestCode == NEW_RECIPE_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
Log.d(TAG, "onActivityResult: " + data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
// mTitleList.add(data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
Recipe rec = new Recipe(data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
mRecipeViewmodel.insert(rec);
} else {
Toast.makeText(
getApplicationContext(),
"saved",
Toast.LENGTH_LONG).show();
}
}
public void startKnownRecipeActivity(int position) {
Log.d(TAG, "startKnownRecipeActivity: Position " + position);
LiveData<List<Recipe>> recipe = mRecipeViewmodel.findById(position);
if (recipe.getValue().size() > 1) {
Log.d(TAG, "startKnownRecipeActivity: Error database found more than one recipe.");
} else {
Log.d(TAG, "startKnownRecipeActivity: Start activity with recipe " + recipe.getValue().get(0).getTitle());
}
}
}
The thing you need to do is to use a call back to send position back to activity.
To make sure that view position is correct you need to override 3 functions in RecyclerView Adapter:
#Override
public int getItemCount() {
return filteredUsers.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
For the Callback just create an Interface:
public interface AdapterListener {
void onClick(int id);
void onClick(ViewModel object);
}
Make a method in your Recycler Adapter:
private AdapterListener adapterListener;
public void setAdapterListener(AdapterListener mCallback) {
this.adapterListener = mCallback;
}
Implement this Interface on your Activity then you will get both methods of the interface.
public class MainActivity extends AppCompatActivity implements AdapterListener{
Register the listener by calling the setAdapterListener method in your activity after the initialization of the RecyclerView
adapterObject.setAdapterListener(MainActivity.this);
Then the last thing you need to do is call interface method in your item onClickListener, where u can either pass the complete model or just the id of the model
adapterListener.onClick(modelObject.getId());
OR
adapterListener.onClick(modelObject);

Styling OssLicensesMenuActivity

I am using a Google library called play-services-plugins to include Open Source Notices on my app.
I could implement it with no problem, but I have no idea how I can style the activity that displays the license.
In my code, I start the activity by calling startActivity(Intent(this, OssLicensesMenuActivity::class.java))
Since OssLicensesMenuActivity is an Activity class, I manage to style like this:
styles.xml:
<style name="LicensesTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">#color/colorPrimaryDark</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
AndroidManifest.xml:
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
android:theme="#style/LicensesTheme" />
This works like a charm, but this activity just displays all the libraries I'm using.
There is a second activity that displays the licence and that's the one I can't figure out how to style. The problem I'm facing is that the code from OssLicensesMenuActivity is obfuscated and I can't find the name and package of the activity class I want to style.
Anyone knows how I can solve this problem?
Just to it's easier to check, the obfuscated code from OssLicensesMenuActivity is the following:
package com.google.android.gms.oss.licenses;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.content.res.Resources.NotFoundException;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AppCompatActivity;
import androidx.loader.app.LoaderManager.LoaderCallbacks;
import androidx.loader.content.Loader;
import com.google.android.gms.common.annotation.KeepForSdk;
import com.google.android.gms.internal.oss_licenses.zzc;
import com.google.android.gms.oss.licenses.R.id;
import com.google.android.gms.oss.licenses.R.layout;
import com.google.android.gms.tasks.Task;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public final class OssLicensesMenuActivity extends AppCompatActivity implements LoaderCallbacks<List<zzc>> {
private static String zzx;
private ListView zzy;
private ArrayAdapter<zzc> zzz;
private boolean zzaa;
private zze zzp;
private Task<String> zzab;
private com.google.android.gms.oss.licenses.zzc zzo;
public OssLicensesMenuActivity() {
}
#KeepForSdk
protected final void onCreate(#Nullable Bundle var1) {
super.onCreate(var1);
this.zzo = com.google.android.gms.oss.licenses.zzc.zza(this);
this.zzaa = fileExistsAndNotEmpty(this, "third_party_licenses") && fileExistsAndNotEmpty(this, "third_party_license_metadata");
Intent var3;
if (zzx == null && (var3 = this.getIntent()).hasExtra("title")) {
zzx = var3.getStringExtra("title");
Log.w("OssLicensesMenuActivity", "The intent based title is deprecated. Use OssLicensesMenuActivity.setActivityTitle(title) instead.");
}
if (zzx != null) {
this.setTitle(zzx);
}
if (this.getSupportActionBar() != null) {
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
if (this.zzaa) {
zzh var10001 = com.google.android.gms.oss.licenses.zzc.zza(this).zzb();
String var4 = this.getPackageName();
zzh var2 = var10001;
this.zzab = var10001.doRead(new zzk(var2, var4));
this.getSupportLoaderManager().initLoader(54321, (Bundle)null, this);
this.zzab.addOnCompleteListener(new zzp(this));
} else {
this.setContentView(layout.license_menu_activity_no_licenses);
}
}
public static void setActivityTitle(#NonNull String var0) {
zzx = var0;
}
#VisibleForTesting(
otherwise = 2
)
#KeepForSdk
static boolean fileExistsAndNotEmpty(#NonNull Context var0, #NonNull String var1) {
InputStream var2 = null;
try {
Resources var3;
String var4 = (var3 = var0.getResources()).getResourcePackageName(id.license_list);
boolean var5 = (var2 = var3.openRawResource(var3.getIdentifier(var1, "raw", var4))).available() > 0;
return var5;
} catch (IOException | NotFoundException var13) {
} finally {
if (var2 != null) {
try {
var2.close();
} catch (IOException var12) {
}
}
}
return false;
}
#KeepForSdk
public final boolean onOptionsItemSelected(MenuItem var1) {
if (var1.getItemId() == 16908332) {
this.finish();
return true;
} else {
return super.onOptionsItemSelected(var1);
}
}
#KeepForSdk
public final void onDestroy() {
this.getSupportLoaderManager().destroyLoader(54321);
super.onDestroy();
}
#KeepForSdk
public final Loader<List<zzc>> onCreateLoader(int var1, Bundle var2) {
return this.zzaa ? new zzo(this, com.google.android.gms.oss.licenses.zzc.zza(this)) : null;
}
#KeepForSdk
public final void onLoadFinished(Loader<List<zzc>> var1, List<zzc> var2) {
this.zzz.clear();
this.zzz.addAll(var2);
this.zzz.notifyDataSetChanged();
}
#KeepForSdk
public final void onLoaderReset(Loader<List<zzc>> var1) {
this.zzz.clear();
this.zzz.notifyDataSetChanged();
}
private class zza extends ArrayAdapter<zzc> {
zza(Context var2) {
OssLicensesMenuActivity.this.zzo;
int var10002 = com.google.android.gms.oss.licenses.zzc.zza(OssLicensesMenuActivity.this.zzp);
OssLicensesMenuActivity.this.zzo;
super(var2, var10002, com.google.android.gms.oss.licenses.zzc.zzb(OssLicensesMenuActivity.this.zzp), new ArrayList());
}
public final View getView(int var1, View var2, ViewGroup var3) {
if (var2 == null) {
OssLicensesMenuActivity.this.zzo;
LayoutInflater var10000 = OssLicensesMenuActivity.this.getLayoutInflater();
zze var6 = OssLicensesMenuActivity.this.zzp;
LayoutInflater var4 = var10000;
XmlResourceParser var7 = var6.zzg.getXml(com.google.android.gms.oss.licenses.zzc.zza(var6));
var2 = var4.inflate(var7, var3, false);
}
OssLicensesMenuActivity.this.zzo;
((TextView)var2.findViewById(com.google.android.gms.oss.licenses.zzc.zzb(OssLicensesMenuActivity.this.zzp))).setText(((zzc)this.getItem(var1)).toString());
return var2;
}
}
}
Just do the same for "OssLicensesActivity" as you did for "OssLicensesMenuActivity" in the Manifest:
<activity android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
android:theme="#style/LicensesTheme" />
This should style the "second activity that displays the licence".

Why is findViewById returning null when trying to get user info?

I have some code whose function is to show the name and age of a user in a RecyclerView but that same RecyclerView is always returning null no matter where I put it.
I tried to put getUserInfo() in onStart() and it didn't work.
I've already looked in other posts in StackOverflow and it still hasn't worked.
My MainActivity.java
package com.pap.diogo.pilltrack;
import android.accounts.Account;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Layout;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity {
private RelativeLayout pills_layout, appoint_layout, add_pills_layout, add_appoints_layout, account_layout, add_button;
private View pills, appointments, add_pills, add_appoints, account;
private TextView AccountName0, AccountAge0;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
Home();
return true;
case R.id.navigation_pills:
Pills();
return true;
case R.id.navigation_appointment:
Appointment();
return true;
case R.id.navigation_account:
Account();
return true;
}
return false;
}
};
public MainActivity() {
}
private void Account(){
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) add_button.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.account);
pills_layout.removeView(pills);
appoint_layout.removeView(appointments);
add_pills_layout.removeView(add_pills);
add_appoints_layout.removeView(add_appoints);
//account_layout.removeAllViews();
//account_layout.addView(account);
add_button.setVisibility(View.VISIBLE);
getUserInfo();
}
private void Appointment() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) add_button.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.add_appoints);
pills_layout.removeView(pills);
appoint_layout.removeView(appointments);
add_pills_layout.removeView(add_pills);
//account_layout.removeView(account);
add_appoints_layout.removeAllViews();
add_appoints_layout.addView(add_appoints);
add_button.setVisibility(View.VISIBLE);
}
private void Pills() {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) add_button.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.add_pills);
pills_layout.removeView(pills);
appoint_layout.removeView(appointments);
add_appoints_layout.removeView(add_appoints);
//account_layout.removeView(account);
add_pills_layout.removeAllViews();
add_pills_layout.addView(add_pills);
add_button.setVisibility(View.VISIBLE);
}
private void Home() {
add_appoints_layout.removeView(add_appoints);
add_pills_layout.removeView(add_pills);
//account_layout.removeView(account);
pills_layout.removeAllViews();
pills_layout.addView(pills);
appoint_layout.removeAllViews();
appoint_layout.addView(appointments);
add_button.setVisibility(View.GONE);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pills_layout = findViewById(R.id.pills_layout);
appoint_layout = findViewById(R.id.appoint_layout);
add_pills_layout = findViewById(R.id.add_pills);
add_appoints_layout = findViewById(R.id.add_appoints);
//account_layout = findViewById(R.id.account);
add_button = findViewById(R.id.add);
AccountName0 = findViewById(R.id.AccountName0);
AccountAge0 = findViewById(R.id.AccountAge0);
LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
pills = inflater.inflate(R.layout.pills, null);
appointments = inflater.inflate(R.layout.appointments, null);
add_pills = inflater.inflate(R.layout.add_pills, null);
add_appoints = inflater.inflate(R.layout.add_appoint, null);
account = inflater.inflate(R.layout.account, null);
pills_layout.addView(pills);
appoint_layout.addView(appointments);
add_button.setVisibility(View.GONE);
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
public void getUserInfo(){
RecyclerView accountUsers;
if ((accountUsers = account.findViewById(R.id.AccountList)) != null)
{
accountUsers.setHasFixedSize(true);
accountUsers.setLayoutManager(new LinearLayoutManager(getBaseContext()));
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final String userid = user.getUid();
final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users");
FirebaseRecyclerOptions<AccountLayout> AccountQ = new FirebaseRecyclerOptions.Builder<AccountLayout>().setQuery(ref, AccountLayout.class).setLifecycleOwner(this).build();
FirebaseRecyclerAdapter<AccountLayout, AccountInfo> AccountAdapter = new FirebaseRecyclerAdapter<AccountLayout, AccountInfo>(AccountQ){
#NonNull
#Override
public AccountInfo onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return new AccountInfo(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.account_layout, viewGroup, false));
}
#Override
protected void onBindViewHolder(#NonNull final AccountInfo holder, int position, #NonNull final AccountLayout model) {
ref.child(userid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
final String name = dataSnapshot.child("name").getValue().toString();
final String age = dataSnapshot.child("idade").getValue().toString();
holder.setName(name);
holder.setAge(age);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
};
accountUsers.setAdapter(AccountAdapter);
}
}
public static class AccountInfo extends RecyclerView.ViewHolder{
View AccountL;
public AccountInfo(#NonNull View itemView) {
super(itemView);
AccountL = itemView;
}
public void setName(String name){
TextView AccountName = AccountL.findViewById(R.id.AccountName0);
AccountName.setText(name);
}
public void setAge(String age){
TextView AccountAge = AccountL.findViewById(R.id.AccountAge0);
AccountAge.setText(age);
}
}
}
My AccountLayout.java
package com.pap.diogo.pilltrack;
public class AccountLayout {
private String name, idade;
public AccountLayout() {
}
public AccountLayout(String name, String idade) {
this.name = name;
this.idade = idade;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIdade() {
return idade;
}
public void setIdade(String idade) {
this.idade = idade;
}
}
My account.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/AccountList"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
Modify your code as below:
public void getUserInfo(){
RecyclerView accountUsers = (RecyclerView) account.findViewById(R.id.AccountList);
if (accountUsers != null)
{
...

E/RecyclerView: No adapter attached; skipping layout (Using Fragment)

I have been reading the different answers here on stackoverflow and on this blog post and tried to implement their solutions but I am still getting the error: No adapter attached; skipping layout.
RecyclerAdapter:
package vn.jupviec.frontend.android.monitor.app.ui.candidate;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.w3c.dom.Text;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import butterknife.BindView;
import vn.jupviec.frontend.android.monitor.app.R;
import vn.jupviec.frontend.android.monitor.app.domain.candidate.TrainingDTO;
import vn.jupviec.frontend.android.monitor.app.util.Utils;
/**
* Created by Windows 10 Gamer on 16/12/2016.
*/
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> {
private static final String TAG = "RecyclerView";
private List<TrainingDTO> mTrainingDTOs;
private Context mContext;
private LayoutInflater mLayoutInflater;
private String today;
private static final DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
AdapterInterface buttonListener;
public RecyclerAdapter(Context context, List<TrainingDTO> datas, AdapterInterface buttonListener) {
mContext = context;
mTrainingDTOs = datas;
this.mLayoutInflater = LayoutInflater.from(mContext);
this.buttonListener = buttonListener;
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.candidate_item, parent, false);
// View itemView = mLayoutInflater.inflate(R.layout.candidate_item, parent, false);
return new RecyclerViewHolder(itemView);
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
final ObjectMapper mapper = new ObjectMapper();
final TrainingDTO trainingDTO = mapper.convertValue(mTrainingDTOs.get(position), TrainingDTO.class);
holder.tvName.setText(trainingDTO.getMaidName());
holder.status.setVisibility(View.GONE);
Date date = new Date();
String currentDate = sdf.format(date);
for (TrainingDTO.TrainingDetailDto td : trainingDTO.getListTrain()) {
today = Utils.formatDate((long) td.getTrainingDate(),"dd/MM/yyyy");
break;
}
if(currentDate.equals(today)) {
holder.status.setVisibility(View.VISIBLE);
holder.status.setText("(Mới)");
}
holder.btnHistory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext,R.string.msg_no_candidate_history,Toast.LENGTH_SHORT).show();
}
});
holder.btnTest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonListener.showComment(trainingDTO);
}
});
}
#Override
public int getItemCount() {
int size ;
if(mTrainingDTOs != null && !mTrainingDTOs.isEmpty()) {
size = mTrainingDTOs.size();
}
else {
size = 0;
}
return size;
}
class RecyclerViewHolder extends RecyclerView.ViewHolder {
private TextView tvName;
private Button btnTest;
private Button btnHistory;
private TextView status;
public RecyclerViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.txtName);
btnTest = (Button) itemView.findViewById(R.id.btnTest);
btnHistory = (Button) itemView.findViewById(R.id.btnHistory);
status = (TextView)itemView.findViewById(R.id.status);
}
}
public boolean removeItem(int position) {
if (mTrainingDTOs.size() >= position + 1) {
mTrainingDTOs.remove(position);
return true;
}
return false;
}
public interface AdapterInterface {
void showComment(TrainingDTO trainingDTO);
void showHistory(TrainingDTO trainingDTO);
}
}
FragmentTapNew:
package vn.jupviec.frontend.android.monitor.app.ui.candidate;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
import vn.jupviec.frontend.android.monitor.app.R;
import vn.jupviec.frontend.android.monitor.app.domain.ResultDTO;
import vn.jupviec.frontend.android.monitor.app.domain.candidate.TrainingDTO;
import vn.jupviec.frontend.android.monitor.app.domain.training.CandidateService;
import vn.jupviec.frontend.android.monitor.app.util.Constants;
import vn.jupviec.frontend.android.monitor.app.util.Utils;
/**
* Created by Windows 10 Gamer on 09/12/2016.
*/
public class FragmentTapNew extends Fragment implements RecyclerAdapter.AdapterInterface {
private static final String TAG = FragmentTapNew.class.getSimpleName();
Activity myContext = null;
private OnItemSelectedListener listener;
ShapeDrawable shapeDrawable;
#BindView(R.id.lvToday)
RecyclerView lvToday;
#BindView(R.id.textView)
TextView textView;
#BindView(R.id.pb_loading)
ProgressBar pbLoading;
private Unbinder unbinder;
private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
ArrayList<TrainingDTO> mTrainingDTO ;
RecyclerAdapter mTrainingDTOAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_candidate_training, container, false);
unbinder = ButterKnife.bind(this, v);
initViews();
return v;
}
private void initViews() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
lvToday.setHasFixedSize(true);
lvToday.setNestedScrollingEnabled(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
today();
}
});
t.start();
}
private boolean isNetworkConnected() {
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni == null) {
Toast.makeText(getActivity(), R.string.err_cannot_establish_connection, Toast.LENGTH_SHORT).show();
return false;
} else
return true;
}
private void today() {
if(isNetworkConnected()){
String token = "a";
Integer date = 0;
setLoadingVisible(true);
CandidateService.getApiDummyClient(getContext()).getCandidate(
token,
date,
Constants.TRAINING,
Arrays.asList(Constants.TRAINING_DAY_NEW),
new Callback<ResultDTO>() {
#Override
public void success(ResultDTO resultDTO, Response response) {
setLoadingVisible(false);
mTrainingDTO = (ArrayList<TrainingDTO>) resultDTO.getData();
if (mTrainingDTO.size() == 0) {
if(textView!=null) {
textView.setVisibility(View.VISIBLE);
textView.setTextColor(Color.RED);
textView.setGravity(Gravity.CENTER | Gravity.BOTTOM);
}
} else {
if(textView!=null) {
textView.setVisibility(View.GONE);
}
if(null==mTrainingDTOAdapter) {
mTrainingDTOAdapter = new RecyclerAdapter(getActivity(), mTrainingDTO, FragmentTapNew.this);
lvToday.setAdapter(mTrainingDTOAdapter);
} else {
lvToday.setAdapter(mTrainingDTOAdapter);
mTrainingDTOAdapter.notifyDataSetChanged();
}
lvToday.invalidate();
}
}
#Override
public void failure(RetrofitError error) {
Log.e(TAG, "JV-ERROR: " + error.getMessage());
Log.e(TAG, "JV-ERROR: " + error.getSuccessType());
}
});
}
}
#Override
public void onResume() {
setLoadingVisible(false);
initViews();
lvToday.setAdapter(mTrainingDTOAdapter);
super.onResume();
}
#Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void setLoadingVisible(boolean visible) {
// pbLoading.getIndeterminateDrawable().setColorFilter(0xFFFF0000, android.graphics.PorterDuff.Mode.MULTIPLY);
if(pbLoading!=null) {
pbLoading.setVisibility(visible ? View.VISIBLE : View.GONE);
lvToday.setVisibility(visible ? View.GONE : View.VISIBLE);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnItemSelectedListener) {
listener = (OnItemSelectedListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " phải implemenet MyListFragment.OnItemSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public void showComment(TrainingDTO trainingDTO) {
Intent intent = new Intent(getContext(), CommentActivity.class);
intent.putExtra(Constants.ARG_NAME_DETAIL, trainingDTO);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
}
#Override
public void showHistory(TrainingDTO trainingDTO) {
Intent intent = new Intent(getContext(), HistoryActivity.class);
intent.putExtra(Constants.ARG_CANDIDATE_HISTORY_DETAIL, trainingDTO);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
}
public interface OnItemSelectedListener {
void showComment(TrainingDTO trainingDTO);
void showHistory(TrainingDTO trainingDTO);
}
}
The first, you don't need to set adapter multiple time, only set adapter at the first time in your method initView().
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
lvToday.setHasFixedSize(true);
lvToday.setNestedScrollingEnabled(false);
if(mTrainingDTO == null) {
mTrainingDTO = new ArrayList<>();
}
if(null == mTrainingDTOAdapter ) {
mTrainingDTOAdapter = new RecyclerAdapter(getActivity(), mTrainingDTO, FragmentTapNew.this);
}
lvToday.setAdapter(mTrainingDTOAdapter);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
today();
}
});
t.start();
After that, you don't need to call lvToday.setAdapter(mTrainingDTOAdapter);
many times. Just call mTrainingDTOAdapter.notifyDataSetChanged(); if having any changes in your data mTrainingDTO.
The errorlog - error:No adapter attached; skipping layout indicates that you've attached LayoutManager but you haven't attached an adapter yet, so recyclerview will skip layout. I'm not sure but, in other words recyclerView will skip layout measuring at the moment.
to prevent this errorLog Try to set an adapter with an empty dataSet i.e. ArrayList or
Attach LayoutManager just before you are setting your adapter.
Try this,
private void initViews() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(getActivity());
lvToday.setLayoutManager(mLinearLayoutManager);
lvToday.setHasFixedSize(true);
lvToday.setNestedScrollingEnabled(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
today();
}
});
t.start();
}

Making a call when button pressed on Arduino

Hi I'm trying to combine 2 projects
1. that tells me wen button on arduino pressed
2. make a call on android
what im trying to do is when button pressed on arduino make a call..
but with no luck :(
Call
package net.mitchtech.adb;
import net.mitchtech.adb.simpledigitalinput.R;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
public class phonecalls extends Activity {
private void call() {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:048598077"));
startActivity(callIntent);
} catch (ActivityNotFoundException activityException) {
Log.e("dialing-example", "Call failed", activityException);
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.input);
}
}
buttons
package net.mitchtech.adb;
import net.mitchtech.adb.simpledigitalinput.R;
import net.mitchtech.adb.phonecalls;
import org.microbridge.server.AbstractServerListener;
import org.microbridge.server.Server;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
public class ButtonView extends FrameLayout {
private static final String TAG = ButtonView.class.getSimpleName();
private final View mButtonView;
private Server mServer;
private final int BUTTON1 = 2;
private final int BUTTON2 = 3;
public ButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mButtonView = inflater.inflate(R.layout.input, this);
}
public void setServer(Server server) {
mServer = server;
mServer.addListener(new AbstractServerListener() {
#Override
public void onReceive(org.microbridge.server.Client client, byte[] data) {
if (data.length < 2)
return;
final int pinNumber = data[0];
final int pinState = data[1];
Log.i(TAG, "data[0]:" + pinNumber + " data[1]:" + pinState);
final TextView positionText = (TextView) findViewById(R.id.activeText);
class InputAction implements Runnable {
public void run() {
switch (pinNumber) {
case BUTTON1:
if (pinState == 1) {
call();
positionText.setText("Button 1 Active");
} else {
positionText.setText("");
}
break;
case BUTTON2:
if (pinState == 1) {
positionText.setText("Button 2 Active");
} else {
positionText.setText("");
}
break;
default:
break;
}
}
};
InputAction action = new InputAction();
post(action);
}
});
}
public View getmButtonView() {
return mButtonView;
}
}
and another activity
package net.mitchtech.adb;
import java.io.IOException;
import net.mitchtech.adb.simpledigitalinput.R;
import org.microbridge.server.Server;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class SimpleDigitalInputActivity extends Activity {
private final static String TAG = SimpleDigitalInputActivity.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Server server = null;
try
{
server = new Server(4567);
server.start();
ButtonView buttonView = (ButtonView) findViewById(R.id.inputView);
buttonView.setServer(server);
} catch (IOException e)
{
Log.e(TAG, "Unable to start TCP server", e);
System.exit(-1);
}
}
}
Your call() function is declared in your activity, but you're trying to access it in your ButtonView class. Try moving it into ButtonView (copy & paste).

Categories

Resources