Switching Activity to firebase- app shuts down

2019-09-19 00:35发布

问题:

I have a problem switching activity when a user would click on a link from MainActivity, the app will just shut down, i am not sure if i have a problem with the project structure or declaring the class correctly and the extends.

Basically what i did is try to implement Firebase example project provided on the website into one activity i have in my app, in order to have a way to let members log in, i striped down the initial code provided here and implemented it in my second activity window, the code in the link is for the MainActivity and i wanted it to be as LoginFragment ( only a name ) didnt use fragments.

thus after minimizing the code ( deleting google, facebook, etc ) options i ended up with this :

package net.we4x4.we4x4;

import android.app.AlertDialog;
import android.app.Application;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.firebase.client.AuthData;
import com.firebase.client.Firebase;
import com.firebase.client.FirebaseError;

import java.util.HashMap;
import java.util.Map;

 public class LoginFragment extends AppCompatActivity{

    private static final String TAG = MainActivity.class.getSimpleName();

    /* *************************************
     *              GENERAL                *
     ***************************************/
/* TextView that is used to display information about the logged in user */
    private TextView mLoggedInStatusTextView;

    /* A dialog that is presented until the Firebase authentication finished. */
    private ProgressDialog mAuthProgressDialog;

    /* A reference to the Firebase */
    private Firebase mFirebaseRef;

    /* Data from the authenticated user */
    private AuthData mAuthData;

    /* Listener for Firebase session changes */
    private Firebase.AuthStateListener mAuthStateListener;

    /* *************************************
     *              PASSWORD               *
     ***************************************/
    private Button mPasswordLoginButton;

    /* *************************************
     *            ANONYMOUSLY              *
     ***************************************/
    private Button mAnonymousLoginButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    /* Load the view and display it */
        setContentView(R.layout.activity_main);

    /* *************************************
     *               PASSWORD              *
     ***************************************/
        mPasswordLoginButton = (Button) findViewById(R.id.login_with_password);
        mPasswordLoginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginWithPassword();
            }
        });

    /* *************************************
     *              ANONYMOUSLY            *
     ***************************************/
    /* Load and setup the anonymous login button */
        mAnonymousLoginButton = (Button) findViewById(R.id.login_anonymously);
        mAnonymousLoginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginAnonymously();
            }
        });

    /* *************************************
     *               GENERAL               *
     ***************************************/
        mLoggedInStatusTextView = (TextView) findViewById(R.id.login_status);

    /* Create the Firebase ref that is used for all authentication with Firebase */
        mFirebaseRef = new Firebase(getResources().getString(R.string.firebase_url));

    /* Setup the progress dialog that is displayed later when authenticating with Firebase */
        mAuthProgressDialog = new ProgressDialog(this);
        mAuthProgressDialog.setTitle("Loading");
        mAuthProgressDialog.setMessage("Authenticating with Firebase...");
        mAuthProgressDialog.setCancelable(false);
        mAuthProgressDialog.show();

        mAuthStateListener = new Firebase.AuthStateListener() {
            @Override
            public void onAuthStateChanged(AuthData authData) {
                mAuthProgressDialog.hide();
                setAuthenticatedUser(authData);
            }
        };
    /* Check if the user is authenticated with Firebase already. If this is the case we can set the authenticated
     * user and hide hide any login buttons */
        mFirebaseRef.addAuthStateListener(mAuthStateListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();


        // if changing configurations, stop tracking firebase session.
        mFirebaseRef.removeAuthStateListener(mAuthStateListener);
    }

    /**
     * This method fires when any startActivityForResult finishes. The requestCode maps to
     * the value passed into startActivityForResult.
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Map<String, String> options = new HashMap<String, String>();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    /* If a user is currently authenticated, display a logout menu */
        if (this.mAuthData != null) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_logout) {
            logout();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Unauthenticate from Firebase and from providers where necessary.
     */
    private void logout() {
        if (this.mAuthData != null) {
        /* logout of Firebase */
            mFirebaseRef.unauth();
            }
        /* Update authenticated user and show login buttons */
            setAuthenticatedUser(null);
        }


    /**
     * This method will attempt to authenticate a user to firebase given an oauth_token (and other
     * necessary parameters depending on the provider)
     */
    private void authWithFirebase(final String provider, Map<String, String> options) {
        if (options.containsKey("error")) {
            showErrorDialog(options.get("error"));
        } else {
            mAuthProgressDialog.show();
            if (provider.equals("twitter")) {
                // if the provider is twitter, we pust pass in additional options, so use the options endpoint
                mFirebaseRef.authWithOAuthToken(provider, options, new AuthResultHandler(provider));
            } else {
                // if the provider is not twitter, we just need to pass in the oauth_token
                mFirebaseRef.authWithOAuthToken(provider, options.get("oauth_token"), new AuthResultHandler(provider));
            }
        }
    }

    /**
     * Once a user is logged in, take the mAuthData provided from Firebase and "use" it.
     */
    private void setAuthenticatedUser(AuthData authData) {
        if (authData != null) {
        /* Hide all the login buttons */
            mPasswordLoginButton.setVisibility(View.GONE);
            mAnonymousLoginButton.setVisibility(View.GONE);
            mLoggedInStatusTextView.setVisibility(View.VISIBLE);
        /* show a provider specific status text */
            String name = null;
            if (authData.getProvider().equals("facebook")
                    || authData.getProvider().equals("google")
                    || authData.getProvider().equals("twitter")) {
                name = (String) authData.getProviderData().get("displayName");
            } else if (authData.getProvider().equals("anonymous")
                    || authData.getProvider().equals("password")) {
                name = authData.getUid();
            } else {
                Log.e(TAG, "Invalid provider: " + authData.getProvider());
            }
            if (name != null) {
                mLoggedInStatusTextView.setText("Logged in as " + name + " (" + authData.getProvider() + ")");
            }
        } else {
        /* No authenticated user show all the login buttons */
            mPasswordLoginButton.setVisibility(View.VISIBLE);
            mAnonymousLoginButton.setVisibility(View.VISIBLE);
            mLoggedInStatusTextView.setVisibility(View.GONE);
        }
        this.mAuthData = authData;
    /* invalidate options menu to hide/show the logout button */
        supportInvalidateOptionsMenu();
    }



    /**
     * Show errors to users
     */
    private void showErrorDialog(String message) {
        new AlertDialog.Builder(this)
                .setTitle("Error")
                .setMessage(message)
                .setPositiveButton(android.R.string.ok, null)
                .setIcon(android.R.drawable.ic_dialog_alert)
                .show();
    }

    /**
     * Utility class for authentication results
     */
    private class AuthResultHandler implements Firebase.AuthResultHandler {

        private final String provider;

        public AuthResultHandler(String provider) {
            this.provider = provider;
        }

        @Override
        public void onAuthenticated(AuthData authData) {
            mAuthProgressDialog.hide();
            Log.i(TAG, provider + " auth successful");
            setAuthenticatedUser(authData);
        }

        @Override
        public void onAuthenticationError(FirebaseError firebaseError) {
            mAuthProgressDialog.hide();
            showErrorDialog(firebaseError.toString());
        }
    }

    /* ************************************
     *              PASSWORD              *
     **************************************
     */
    public void loginWithPassword() {
        mAuthProgressDialog.show();
        mFirebaseRef.authWithPassword("test@firebaseuser.com", "test1234", new AuthResultHandler("password"));
    }

    /* ************************************
     *             ANONYMOUSLY            *
     **************************************
     */
    private void loginAnonymously() {
        mAuthProgressDialog.show();
        mFirebaseRef.authAnonymously(new AuthResultHandler("anonymous"));
    }



public void switchToRegister(View v) {
    Intent Register = new Intent(this, Register.class);
    startActivity(Register);
}

}

and as you would guys see i declared the class as public and extended AppCompatActivity ( not sure what i had to extend just learned that from another tutorial ) i also tried to extend it from Application, which i thought could work, but then all sort of errors poped up in the code listed :

in the manifesto :

 <?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme" >
    <activity
        android:name="net.we4x4.we4x4.MainActivity"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <activity android:name=".LoginFragment">
    </activity>

    <activity android:name=".Register">
    </activity>

    <!-- ATTENTION: This was auto-generated to add Google Play services to your project for
         App Indexing.  See https://g.co/AppIndexing/AndroidStudio for more information. -->
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
</application>

in line 27 under .LoginFragment it says that it is not assignable to android.app.activity ?

and then in the code itself LoginFragment :

i get these errors which i could not solve : line 58 - setContentView cant resolve this method ? setContentView(R.layout.fragment_login);

line 63 findViewById also cant resolve this method ?

         mPasswordLoginButton = (Button) findViewById(R.id.login_with_password);

the same anonymous option line 75 mAnonymousLoginButton = (Button) findViewById(R.id.login_anonymously);

the same problem with line 86 findViewById ? mLoggedInStatusTextView = (TextView) findViewById(R.id.login_status);

Apparently i need to create findViewById mehtod if i want to extends Application, but i did not proceed with this since i do not know if i should extends from Application, considering i do not get any of these errors in the code when i extends from MainActivity or AppCompatActivity

also i get on line 114 cant resolve this method super.onDestroy();

and few others .... ?

so i am not sure how to solve this problem ? should i extends Application and tackle these errors ( and how to solve these errrors ) or keep the extend of MainActivity or AppCompatActivity ? which contain no error in the code but will not function properly switching activity:

my MainActivity is :

 package net.we4x4.we4x4;

import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.v7.app.AppCompatActivity;
 import android.view.View;
 import android.widget.MediaController;
 import android.widget.VideoView;

 import com.firebase.client.Firebase;

 public class MainActivity extends AppCompatActivity {
public static final String VID_URL = "http://res.cloudinary.com/wi4x4/video/upload/v1457270321/bolivia_njb6r0.mp4";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState == null) {
        Firebase.setAndroidContext(this);


    VideoView vid = (VideoView)findViewById(R. id.VidClip);
    Uri video = Uri.parse(VID_URL);
    vid.setMediaController(new MediaController(this));
    vid.setVideoURI(video);
    vid.requestFocus();


}
 }


public void switchToLoginFragment(View v) {
    Intent LoginFragment = new Intent(this, LoginFragment.class);
    startActivity(LoginFragment);
}
public void switchToRegister(View v) {
    Intent Register = new Intent(this, Register.class);
    startActivity(Register);
}

}

and the error log is :

 6:16:51 PM AssertionError: Wrong element range PsiJavaFile:LoginFragment.java; committed=true

android monitor :

 03-07 18:19:52.512 21730-21730/net.we4x4.we4x4 E/AndroidRuntime: FATAL EXCEPTION: main
                                                             Process: net.we4x4.we4x4, PID: 21730
                                                             java.lang.RuntimeException: Unable to start activity ComponentInfo{net.we4x4.we4x4/net.we4x4.we4x4.LoginFragment}: java.lang.IllegalStateException: For a custom firebase host you must first set your authentication server before using authentication features!
                                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2429)
                                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2493)
                                                                 at android.app.ActivityThread.access$800(ActivityThread.java:166)
                                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283)
                                                                 at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                 at android.os.Looper.loop(Looper.java:136)
                                                                 at android.app.ActivityThread.main(ActivityThread.java:5584)
                                                                 at java.lang.reflect.Method.invokeNative(Native Method)
                                                                 at java.lang.reflect.Method.invoke(Method.java:515)
                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
                                                                 at dalvik.system.NativeStart.main(Native Method)
                                                              Caused by: java.lang.IllegalStateException: For a custom firebase host you must first set your authentication server before using authentication features!
                                                                 at com.firebase.client.authentication.AuthenticationManager.checkServerSettings(AuthenticationManager.java:221)
                                                                 at com.firebase.client.authentication.AuthenticationManager.addAuthStateListener(AuthenticationManager.java:625)
                                                                 at com.firebase.client.Firebase.addAuthStateListener(Firebase.java:555)
                                                                 at net.we4x4.we4x4.LoginFragment.onCreate(LoginFragment.java:107)
                                                                 at android.app.Activity.performCreate(Activity.java:5447)
                                                                 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
                                                                 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2393)
                                                                 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2493) 
                                                                 at android.app.ActivityThread.access$800(ActivityThread.java:166) 
                                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1283) 
                                                                 at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                 at android.os.Looper.loop(Looper.java:136) 
                                                                 at android.app.ActivityThread.main(ActivityThread.java:5584) 
                                                                 at java.lang.reflect.Method.invokeNative(Native Method) 
                                                                 at java.lang.reflect.Method.invoke(Method.java:515) 
                                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) 
                                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) 
                                                                 at dalvik.system.NativeStart.main(Native Method) 

回答1:

This exception:

java.lang.RuntimeException: Unable to start activity ComponentInfo{net.we4x4.we4x4/net.we4x4.we4x4.LoginFragment}: java.lang.IllegalStateException: For a custom firebase host you must first set your authentication server before using authentication features!

Comes from this line:

mFirebaseRef = new Firebase(getResources().getString(R.string.firebase_url));

The reason is that firebase_url is not in the form https://yours.firebaseio.com.