33

my app crashes when trying to display server message and I think the problem could be with my getView(). below is the registerActivity were the crash occurs and my activity_register.xml

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.fastchat.helper.SQLiteHandler;
import com.fastchat.helper.SessionManager;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


public class RegisterActivity extends Activity {

private static final String TAG = RegisterActivity.class.getSimpleName();
private Button btnRegister;
private Button btnLinkToLogin;
private EditText inputFullName;
private EditText inputEmail;
private EditText inputPassword;
private ProgressDialog pDialog;
private SessionManager session;
private SQLiteHandler db;
private ProgressBar progress;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_register);


    inputFullName = (EditText) findViewById(R.id.name);
    inputEmail = (EditText) findViewById(R.id.email);
    inputPassword = (EditText) findViewById(R.id.password);
    btnRegister = (Button) findViewById(R.id.btnRegister);
    btnLinkToLogin = (Button) findViewById(R.id.btnLinkToLoginScreen);

    // Progress dialog
    pDialog = new ProgressDialog(this);
    pDialog.setCancelable(true);

    /*
    // Session manager
    session = new SessionManager(getApplicationContext());

    // SQLite database handler
    db = new SQLiteHandler(getApplicationContext());

    // Check if user is already logged in or not
   if (session.isLoggedIn()) {
        // User is already logged in. Take him to main activity
        Intent intent = new Intent(RegisterActivity.this,
                SearchableActivity.class);
        startActivity(intent);
        finish();

    }
*/
    // Register Button Click event
    btnRegister.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {
            String name = inputFullName.getText().toString();
            String email = inputEmail.getText().toString();
            String password = inputPassword.getText().toString();

            if (!name.isEmpty() && !email.isEmpty() && !password.isEmpty()) {
                registerProcess(name, email, password);
            } else {
                Toast.makeText(getApplicationContext(),
                        "Please enter your details!", Toast.LENGTH_LONG)
                        .show();
            }
        }
    });

    // Link to Login Screen
    btnLinkToLogin.setOnClickListener(new View.OnClickListener() {

        public void onClick(View view) {
            Intent i = new Intent(getApplicationContext(),
                    LoginActivity.class);
            startActivity(i);
            finish();
        }
    });

}   

 private void registerProcess(String name,String email,String password){

    String tag_string_req = "req_register";
    //pDialog = new AlertDialog.Builder(getActivity());
    pDialog.setMessage("please wait");
    pDialog.show();


    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(Constants.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    RequestInterface requestInterface = retrofit.create(RequestInterface.class);

    User user = new User();
    user.setName(name);
    user.setEmail(email);
    user.setPassword(password);
    ServerRequest request = new ServerRequest();
    request.setOperation(Constants.REGISTER_OPERATION);
    request.setUser(user);
    Call<ServerResponse> response = requestInterface.operation(request);

    response.enqueue(new Callback<ServerResponse>() {
        private View view;

        public View getView() {
            return view;

        }

        @Override
        public void onResponse(Call<ServerResponse> call, retrofit2.Response<ServerResponse> response) {

            ServerResponse resp = response.body();

           if(resp !=null)//tried to check if resp is null but its not

//crash occurs here
            Snackbar.make(getView(),resp.getMessage(), Snackbar.LENGTH_LONG).show();
            pDialog.dismiss();
        }


        @Override
        public void onFailure(Call<ServerResponse> call, Throwable t) {

           // progress.setVisibility(View.INVISIBLE);
            Log.d(Constants.TAG, "failed");
            Toast.makeText(getApplicationContext(), t.getLocalizedMessage(), Toast.LENGTH_LONG).show();
            pDialog.dismiss();


        }
    });
}

activity_register.xml

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/bg_register"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp"
android:id="@+id/chat">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical"
    android:paddingLeft="20dp"
    android:paddingRight="20dp" >

    <ImageView
        android:layout_width="389dp"
        android:layout_height="72dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="24dp"
        android:src="@drawable/logo"
        tools:ignore="ContentDescription" />


    <EditText
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:background="@color/input_register_bg"
        android:hint="@string/hint_name"
        android:padding="10dp"
        android:singleLine="true"
        android:inputType="textCapWords"
        android:textColor="@color/input_register"
        android:textColorHint="@color/input_register_hint" />

    <EditText
        android:id="@+id/email"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:background="@color/input_register_bg"
        android:hint="@string/hint_email"
        android:inputType="textEmailAddress"
        android:padding="10dp"
        android:singleLine="true"
        android:textColor="@color/input_register"
        android:textColorHint="@color/input_register_hint" />

    <EditText
        android:id="@+id/password"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:background="@color/input_register_bg"
        android:hint="@string/hint_password"
        android:inputType="textPassword"
        android:padding="10dp"
        android:singleLine="true"
        android:textColor="@color/input_register"
        android:textColorHint="@color/input_register_hint" />

    <!-- Login Button -->

    <Button
        android:id="@+id/btnRegister"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dip"
        android:background="#ea4c88"
        android:text="register"
        android:textColor="@color/white" />

    <!-- Link to Login Screen -->

    <Button
        android:id="@+id/btnLinkToLoginScreen"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dip"
        android:background="@null"
        android:text="already a member? login"
        android:textAllCaps="false"
        android:textColor="@color/white"
        android:textSize="15dp" />
</LinearLayout>

below is logcat message

 java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid view.
                                                              at android.support.design.widget.Snackbar.make(Snackbar.java:137)
                                                              at com.chat.RegisterActivity$3.onResponse(RegisterActivity.java:143)
                                                              at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
                                                              at android.os.Handler.handleCallback(Handler.java:739)
                                                              at android.os.Handler.dispatchMessage(Handler.java:95)
Mani
  • 423
  • 1
  • 4
  • 13
  • 1
    You need a valid view here: Snackbar.make(getView(),resp.getMessage(), Snackbar.LENGTH_LONG).show(); , you can use any view referenced in your activity. – diegoveloper Dec 06 '17 at 04:19

13 Answers13

48

I suggest that you to try with findViewById(android.R.id.content).

This is what did the trick for me:

Snackbar.make(findViewById(android.R.id.content), resp.getMessage(), Snackbar.LENGTH_LONG).show();

android.R.id.content will give you the root element of the view (for more information on that, please check Android: What is android.R.id.content used for?).

Normando
  • 596
  • 5
  • 4
14

I found one solution that may help others who are looking for common solution.

I got this error when I have tried to show message with Snackbar before loading our whole XML file.

In fragment I have tried to call API in onCreateView(); and showing Snackbar message of Internet connection is off as below:

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    mBindingObject = DataBindingUtil.inflate(inflater, getLayoutResId(), container, false);

    getData();

    return mBindingObject.getRoot();
}

I just put that method in onViewCreated()

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    getData();
}

Its working for me now.

BONUS:

Always try to use view after its loaded successfully. Each and every position of one line is matters.

Thank you.

Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
4

Wrap your layout with CoordinatorLayout

<android.support.design.widget.CoordinatorLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:id="@+id/chat"
     android:layout_height="match_parent">
     <LinearLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@color/bg_register"
          android:gravity="center"
          android:orientation="vertical"
          android:padding="10dp">
               ...
               ...
               ...
    </LinearLayout>
</android.support.design.widget.CoordinatorLayout>
Anu Martin
  • 711
  • 1
  • 9
  • 20
  • 2
    This is the most appropriate answer for me. As per the docs, one of the parent views has to be a CoordinatorLayout. See Snackbar [docs](https://developer.android.com/reference/com/google/android/material/snackbar/Snackbar#make(android.content.Context,%20android.view.View,%20java.lang.CharSequence,%20int)) – Peter Chaula Apr 24 '22 at 09:36
  • 1
    This is the right answer. You can also use "requireActivity().findViewById(R.id.CoordinatorLayout)" – Tarique Anowar Jun 17 '22 at 01:36
2

I had this problem too ... of course with a little difference ...

PROBLEM: I used MVVM architecture and LiveData observer for showing SnackBar by the following code...This error occurred to me when I was displaying another fragment and returning back again.

 myViewModel.mSnackbar.observe(this, new SnackBarText.SnackbarTextObserver() {
        @Override
        public void onNewMessage(@NotNull YourSnackBarClass msg) {
            // Showing the message on SnackBar
            Snackbar.make(view, msg.getMessage(), Snackbar.LENGTH_LONG).show();
        }
    });

SOLUTION: I remove this observer when fragment paused (Because I used replace() on fragment transaction)

// fragment area
@Override
protected void onPause() {
    super.onPause();
    mSnackbar.removeObservers(owner)
}
ultra.deep
  • 1,699
  • 1
  • 19
  • 23
1

Replace your View with this

getActivity().getCurrentFocus().

but not in your Default Fragment

Harshith Rai
  • 3,018
  • 7
  • 22
  • 35
1

Using KOTLIN

activity?.window?.decorView?.rootView?.snack("Done !!")

fun View.snack(str: String) = Snackbar.make(this, str, Snackbar.LENGTH_SHORT).show()

or if you inside an activity simple remove activity?.

Mohamed Slama
  • 189
  • 1
  • 3
  • 17
0

You are passing invalid view argument to Snackbar. so you've to give RegisterActivity BaseLayout reference to it. you should try declare id to activity_register.xml Linear / Relative or whatever you design.

  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:background="#a7b6bdd6"
    android:id="@+id/ll1"  //here 
     >

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:background="@color/colorPrimary"
        android:minHeight="?attr/actionBarSize" />

        //your design

</LinearLayout>

then initialise pass this layout to snackbar like below

 private void registerProcess(String name,String email,String password){

     final LinearLayout linearLayout = (LinearLayout)findViewById(R.id.ll1);// here change
      //Snackbar.make(linearLayout,"Hello", Snackbar.LENGTH_LONG).show();

    String tag_string_req = "req_register";
    //pDialog = new AlertDialog.Builder(getActivity());
    pDialog.setMessage("please wait");
    pDialog.show();


    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(Constants.BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    RequestInterface requestInterface = retrofit.create(RequestInterface.class);

    User user = new User();
    user.setName(name);
    user.setEmail(email);
    user.setPassword(password);
    ServerRequest request = new ServerRequest();
    request.setOperation(Constants.REGISTER_OPERATION);
    request.setUser(user);
    Call<ServerResponse> response = requestInterface.operation(request);

    response.enqueue(new Callback<ServerResponse>() {
        private View view;

        public View getView() {
            return view;

        }

        @Override
        public void onResponse(Call<ServerResponse> call, retrofit2.Response<ServerResponse> response) {

            ServerResponse resp = response.body();

           if(resp !=null)//tried to check if resp is null but its not

//crash occurs here
            Snackbar.make(linearLayout,resp.getMessage(), Snackbar.LENGTH_LONG).show();
            pDialog.dismiss();
        }


        @Override
        public void onFailure(Call<ServerResponse> call, Throwable t) {

           // progress.setVisibility(View.INVISIBLE);
            Log.d(Constants.TAG, "failed");
            Toast.makeText(getApplicationContext(), t.getLocalizedMessage(), Toast.LENGTH_LONG).show();
            pDialog.dismiss();


        }
    });
}
Omkar
  • 3,040
  • 1
  • 22
  • 42
0

Not sure if this is really that useful, but I stumbled across this issue when I was trying to display a Snackbar, using a CoordinatorLayout view which had android:fitSystemWindows="true" and android:layout_behavior="...BottomSheetBehavior" apparently you cannot prompt a Snackbar on a root view which also has a behavior set.

I was doing some refactor and then realized that it didn't make any sense, having a behavior set on the root view. So I wrapped the CoordinatorLayout inside another coordinator, use that new root view as the view for the Snackbar, and everything worked perfectly.

4gus71n
  • 3,717
  • 3
  • 39
  • 66
0

If you get this error for Show SnackBar you should use CoordinatorLayout in your layout:

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:id="@+id/coordinator"
    android:layout_height="match_parent">

and in your code:

val snack = Snackbar.make(
    binding.coordinator,
    getString(R.string.verification_failed) + e.message,
    Snackbar.LENGTH_LONG
)

snack.show()
Boken
  • 4,825
  • 10
  • 32
  • 42
Sana Ebadi
  • 6,656
  • 2
  • 44
  • 44
0

for me, it is because i initialize SnackBar before setContentView(View)

before

View v = binding.getRoot();
snackbar = new SnackBarHelper(v); // helper class to init a snackbar

setContentView(v);

and then, after i reorder the code like this

View v = binding.getRoot();
setContentView(v);

snackbar = new SnackBarHelper(v);

it works.

Denny Sitorus
  • 108
  • 1
  • 5
-1

Instead of this :

Snackbar.make(getView(),resp.getMessage(), Snackbar.LENGTH_LONG).show();

Replace getView() with an existing view component of your current activity, like this:

Snackbar.make(findViewById(R.id. chat),resp.getMessage(), Snackbar.LENGTH_LONG).show();
diegoveloper
  • 93,875
  • 20
  • 236
  • 194
-1

This error happened because you try to get view don't there in that fragment or activity.

-2

To solve this Exception, you can do this.

 private void CrearSnackBar(String mensaje)
{
    Snackbar snackbar = Snackbar
            .make(constraintLayout, mensaje, Snackbar.LENGTH_LONG)
            .setActionTextColor(getResources().getColor(R.color.colorWhite))
            .setAction(getResources().getString(R.string.label_settings), new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent myIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    startActivity(myIntent);
                }
            });


    View sbView = snackbar.getView();
    snackbar.show();
}

Where constraintLayout is the layout parent where I want to show the message, declare the layout:

ConstraintLayout constraintLayout;

And find it by Id.

constraintLayout = findViewById(R.id.cl_layout);

The function works for me. I hope it could help you.