Я много искал через stackoverflow, но я не мог найти ответ, который разрешает мою проблему. Поэтому я публикую это.
У меня есть пример приложения для Android, в котором я пытаюсь использовать facebook Login. Вот шаги, которые я выполнил:
Окружающая среда: Android-версия Android SDK версии: 22 Facebook SDK: 4.0
Последующие шаги по установке FB APK на эмулятор, сгенерировали ключ хеширования разработчика и обновили его в настройках app->. У моего манифеста Android есть этот код
<uses-permission android:name="android.permission.INTERNET"/> <activity android:name="com.facebook.FacebookActivity" android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:label="@string/app_name" /> <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
В файле макета activity_main.xml у меня есть этот фрагмент кода
<com.facebook.login.widget.LoginButton android:id="@+id/fblogin_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="30dp" android:layout_marginBottom="30dp" />
И, наконец, в моей основной деятельности у меня есть это
public class MainActivity extends Activity { LoginButton loginButton; CallbackManager callbackManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FacebookSdk.sdkInitialize(getApplicationContext()); callbackManager = CallbackManager.Factory.create(); loginButton = (LoginButton) findViewById(R.id.fblogin_button); loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() { @Override public void onSuccess(LoginResult loginResult) { Toast.makeText(getApplicationContext(),"Fb Login Success",Toast.LENGTH_LONG); } @Override public void onCancel() { Toast.makeText(getApplicationContext(),"Fb on cancel",Toast.LENGTH_LONG); } @Override public void onError(FacebookException e) { Toast.makeText(getApplicationContext(),"Fb Login Error",Toast.LENGTH_LONG); } }); setContentView(R.layout.activity_main); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data){ super.onActivityResult(requestCode, resultCode, data); Log.d("Inside Fb login","on Activiry result"); callbackManager.onActivityResult(requestCode, resultCode, data); }}
Я получаю исключение нулевого указателя, как показано ниже
java.lang.RuntimeException: Unable to start activity componentInfo{PROJECT.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.facebook.login.widget.LoginButton.registerCallback(com.facebook.CallbackManager, com.facebook.FacebookCallback)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) at android.app.ActivityThread.access$800(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
Что мне здесь не хватает?
Похоже, вы получаете NullPointerException
потому что вы вызываете findViewById()
перед вызовом setContentView()
, поэтому loginButton
имеет значение null, когда вы вызываете loginButton.registerCallback()
.
Просто переместите вызов setContentView()
вверху:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FacebookSdk.sdkInitialize(getApplicationContext()); setContentView(R.layout.activity_main); //Moved up here to resolve NPE callbackManager = CallbackManager.Factory.create(); loginButton = (LoginButton) findViewById(R.id.fblogin_button); loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() { @Override public void onSuccess(LoginResult loginResult) { Toast.makeText(getApplicationContext(),"Fb Login Success",Toast.LENGTH_LONG); } @Override public void onCancel() { Toast.makeText(getApplicationContext(),"Fb on cancel",Toast.LENGTH_LONG); } @Override public void onError(FacebookException e) { Toast.makeText(getApplicationContext(),"Fb Login Error",Toast.LENGTH_LONG); } }); }
AndoridMenifest.xml
похоже, связана с приложением, которое мы устанавливаем в файле AndoridMenifest.xml
. Поскольку я понял, что когда facebook sdk связывается для создания LoginFramment
тогда ApplicationId отправляется как null
Здесь используется метод com.facebook.login.LoginFragment
класса com.facebook.login.LoginFragment
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(savedInstanceState != null) { this.loginClient = (LoginClient)savedInstanceState.getParcelable("loginClient"); this.loginClient.setFragment(this); } else { this.loginClient = new LoginClient(this); } this.loginClient.setOnCompletedListener(new OnCompletedListener() { public void onCompleted(Result outcome) { LoginFragment.this.onLoginClientCompleted(outcome); } }); FragmentActivity activity = this.getActivity(); if(activity != null) { this.initializeCallingPackage(activity); if(activity.getIntent() != null) { //the applicationId in this.request object is null this.request = (Request)activity.getIntent().getParcelableExtra("request"); } } }
Как указано в столбце varoius, applicationId приходит в нуль, потому что строковый ресурс app_id
корректно обрабатывается андроидом. https://github.com/jamesward/AndroidStringBug
Я решил эту задачу, установив applicationId вручную после инициализации facebook sdk, как указано ниже в методе onCreate
.
FacebookSdk.sdkInitialize(getApplicationContext()); FacebookSdk.setApplicationId(getResources().getString(R.string.app_id)); mFacebookCallbackManager = CallbackManager.Factory.create();