Inicio de sesión de Facebook con Android SDK 3.0 que provoca ANR o no funciona en absoluto

Para registrar un usuario en Facebook en una aplicación para Android, intento utilizar el siguiente código. Una vez que el usuario ha iniciado sesión, todas las ubicaciones de sus amigos deben ser buscadas.

Desafortunadamente, este código causa ANRs a veces (como se indica en la consola de desarrolladores de Google Play) ya veces simplemente no funciona. Si quito la aplicación dentro de Facebook (revocar permisos), el permiso de diálogo se muestra de nuevo en el próximo lanzamiento de la aplicación para Android. Pero si la aplicación tiene los permisos ya, hace que los ANRs o simplemente se cierra sin éxito.

Parece que las partes están funcionando y las partes están equivocadas, ¿no? ¿Es el código siguiente una forma correcta de iniciar sesión y obtener datos?

package com.my.application; import java.util.Arrays; import java.util.List; import org.json.JSONArray; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.preference.PreferenceManager; import com.facebook.*; import com.facebook.Session.OpenRequest; import com.facebook.Session.StatusCallback; public class FBLocations extends Activity { private Session.StatusCallback fbStatusCallback = new Session.StatusCallback() { @Override public void call(Session session, SessionState state, Exception exception) { // callback for session state changes if (state.isOpened()) { Request.executeGraphPathRequestAsync(session, "me/friends/?access_token="+session.getAccessToken()+"&fields=id,name,location&limit=500", new Request.Callback() { @Override public void onCompleted(Response response) { if (response != null) { // do something with <response> now } } }); } } }; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); try { openActiveSession(this, true, fbStatusCallback, Arrays.asList("friends_location")); } catch (Exception e) { e.printStackTrace(); } } private static Session openActiveSession(Activity activity, boolean allowLoginUI, StatusCallback callback, List<String> permissions) { OpenRequest openRequest = new OpenRequest(activity).setPermissions(permissions).setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK).setCallback(callback).setDefaultAudience(SessionDefaultAudience.FRIENDS); Session session = new Session.Builder(activity).build(); if (SessionState.CREATED_TOKEN_LOADED.equals(session.getState()) || allowLoginUI) { Session.setActiveSession(session); session.openForRead(openRequest); return session; } return null; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data); } } 

También he añadido hashes clave de la aplicación a Facebook, tanto de depuración y producción. No estaba seguro de si el relleno = tiene que ser escrito también.

Introduzca aquí la descripción de la imagen

No pude seguir el tutorial oficial de Facebook, ya que no usaré el botón de inicio de sesión del SDK ni tampoco usaré fragmentos en Android.

Edición (7 de enero de 2013):

Después de que Hartok sugirió reemplazar session.isOpened() por state.isOpened() en el método call() callback, las cosas funcionan en el 50% de todas las pruebas ahora. Sin embargo, hay algunos problemas. En algunos casos, todo funciona bien, en algunos otros casos (sin que yo haga nada diferente), hay el siguiente error en LogCat:

 01-07 01:55:29.882: W/System.err(30572): com.facebook.FacebookException: Log in attempt aborted. at com.facebook.Session.close(Session.java:572) at com.facebook.Session.setActiveSession(Session.java:755) at my.app.package.FBImport.openActiveSession(FBImport.java:145) // this is: Session.setActiveSession(session); at my.app.package.FBImport.access$5(FBImport.java:139) at my.app.package.FBImport$4.run(FBImport.java:124) 

¿Qué causa este error? ¿Problema del cliente o problema del servidor? La aplicación parece congelarse (ANR) después de eso, por cierto.

Y si trato de conectar dos veces en secuencia, veo la siguiente salida LogCat:

 java.lang.IllegalStateException: Cannot execute task: the task is already running. at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:550) at android.os.AsyncTask.execute(AsyncTask.java:511) at com.facebook.RequestAsyncTask.executeOnSettingsExecutor(RequestAsyncTask.java:186) at com.facebook.Request.executeBatchAsync(Request.java:1094) at com.facebook.Request.executeBatchAsync(Request.java:1073) at com.facebook.Request.executeBatchAsync(Request.java:1055) at com.facebook.Request.executeAsync(Request.java:852) 

¿Porqué es eso? ¿Por qué sigue funcionando la tarea?

Descripción de ANR (ANR keyDispatchingTimedOut):

 DALVIK THREADS: (mutexes: tll=0 tsl=0 tscl=0 ghl=0) "main" prio=5 tid=1 NATIVE | group="main" sCount=1 dsCount=0 obj=0x4184e9a0 self=0x40011010 | sysTid=19301 nice=0 sched=0/0 cgrp=apps handle=1074414556 | state=S schedstat=( 906984000 397085000 2526 ) utm=66 stm=24 core=0 #00 pc 00017ee4 /system/lib/libc.so (epoll_wait+12) #01 pc 00014b09 /system/lib/libutils.so (android::Looper::pollInner(int)+96) #02 pc 00014d71 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+104) #03 pc 0005ed53 /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22) #04 pc 0001e290 /system/lib/libdvm.so (dvmPlatformInvoke+112) #05 pc 0004d411 /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+396) #06 pc 000276a0 /system/lib/libdvm.so #07 pc 0002b57c /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184) #08 pc 0005ff07 /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374) #09 pc 000677e1 /system/lib/libdvm.so #10 pc 000276a0 /system/lib/libdvm.so #11 pc 0002b57c /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184) #12 pc 0005fc31 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272) #13 pc 000499fb /system/lib/libdvm.so #14 pc 00046871 /system/lib/libandroid_runtime.so #15 pc 00047533 /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+390) #16 pc 00000db7 /system/bin/app_process #17 pc 0001271f /system/lib/libc.so (__libc_init+38) #18 pc 00000ae8 /system/bin/app_process at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:125) at android.os.Looper.loop(Looper.java:124) at android.app.ActivityThread.main(ActivityThread.java:5039) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) at dalvik.system.NativeStart.main(Native Method) "AsyncTask #2" prio=5 tid=17 WAIT | group="main" sCount=1 dsCount=0 obj=0x4205f6d0 self=0x6742f940 | sysTid=19354 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1732251672 | state=S schedstat=( 82839000 103493000 646 ) utm=5 stm=3 core=0 at java.lang.Object.wait(Native Method) - waiting on <0x4205f7f0> (a java.lang.VMThread) held by tid=17 (AsyncTask #2) at java.lang.Thread.parkFor(Thread.java:1231) at sun.misc.Unsafe.park(Unsafe.java:323) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:856) "Binder_3" prio=5 tid=16 NATIVE | group="main" sCount=1 dsCount=0 obj=0x41fed668 self=0x41838008 | sysTid=19330 nice=0 sched=0/0 cgrp=apps handle=1742766600 | state=S schedstat=( 1078000 818000 10 ) utm=0 stm=0 core=0 #00 pc 00016fe4 /system/lib/libc.so (__ioctl+8) #01 pc 0002a97d /system/lib/libc.so (ioctl+16) #02 pc 00016ba1 /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+132) #03 pc 00017363 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+154) #04 pc 0001b15d /system/lib/libbinder.so #05 pc 00011267 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+114) #06 pc 0004679f /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+66) #07 pc 00010dcd /system/lib/libutils.so #08 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72) #09 pc 0000dac4 /system/lib/libc.so (pthread_create+160) at dalvik.system.NativeStart.run(Native Method) "pool-1-thread-5" prio=5 tid=15 WAIT | group="main" sCount=1 dsCount=0 obj=0x420423d0 self=0x673d8ab8 | sysTid=19329 nice=0 sched=0/0 cgrp=apps handle=1732087560 | state=S schedstat=( 6292000 7083000 36 ) utm=0 stm=0 core=2 at java.lang.Object.wait(Native Method) - waiting on <0x42042528> (a java.lang.VMThread) held by tid=15 (pool-1-thread-5) at java.lang.Thread.parkFor(Thread.java:1231) at sun.misc.Unsafe.park(Unsafe.java:323) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:856) "pool-1-thread-4" prio=5 tid=14 WAIT | group="main" sCount=1 dsCount=0 obj=0x42039040 self=0x673cb248 | sysTid=19328 nice=0 sched=0/0 cgrp=apps handle=1732032152 | state=S schedstat=( 8178000 7047000 32 ) utm=0 stm=0 core=3 at java.lang.Object.wait(Native Method) - waiting on <0x42039160> (a java.lang.VMThread) held by tid=14 (pool-1-thread-4) at java.lang.Thread.parkFor(Thread.java:1231) at sun.misc.Unsafe.park(Unsafe.java:323) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:856) "pool-1-thread-3" prio=5 tid=13 WAIT | group="main" sCount=1 dsCount=0 obj=0x42027140 self=0x673c95f8 | sysTid=19327 nice=0 sched=0/0 cgrp=apps handle=1698808232 | state=S schedstat=( 10642000 19156000 34 ) utm=1 stm=0 core=1 at java.lang.Object.wait(Native Method) - waiting on <0x42027260> (a java.lang.VMThread) held by tid=13 (pool-1-thread-3) at java.lang.Thread.parkFor(Thread.java:1231) at sun.misc.Unsafe.park(Unsafe.java:323) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:856) "pool-1-thread-2" prio=5 tid=12 WAIT | group="main" sCount=1 dsCount=0 obj=0x4201d958 self=0x672cd008 | sysTid=19326 nice=0 sched=0/0 cgrp=apps handle=1731988480 | state=S schedstat=( 17725000 16571000 59 ) utm=1 stm=0 core=3 at java.lang.Object.wait(Native Method) - waiting on <0x4201da78> (a java.lang.VMThread) held by tid=12 (pool-1-thread-2) at java.lang.Thread.parkFor(Thread.java:1231) at sun.misc.Unsafe.park(Unsafe.java:323) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:856) "pool-1-thread-1" prio=5 tid=11 WAIT | group="main" sCount=1 dsCount=0 obj=0x420156c8 self=0x65dc8818 | sysTid=19325 nice=0 sched=0/0 cgrp=apps handle=1728232912 | state=S schedstat=( 11166000 9311000 77 ) utm=0 stm=1 core=2 at java.lang.Object.wait(Native Method) - waiting on <0x42015810> (a java.lang.VMThread) held by tid=11 (pool-1-thread-1) at java.lang.Thread.parkFor(Thread.java:1231) at sun.misc.Unsafe.park(Unsafe.java:323) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1013) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1073) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) at java.lang.Thread.run(Thread.java:856) "AsyncTask #1" prio=5 tid=10 WAIT | group="main" sCount=1 dsCount=0 obj=0x41fb5990 self=0x63bd3008 | sysTid=19318 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1748684416 | state=S schedstat=( 24263000 18668000 33 ) utm=1 stm=1 core=1 at java.lang.Object.wait(Native Method) - waiting on <0x41fd07d0> (a java.lang.VMThread) held by tid=10 (AsyncTask #1) at java.lang.Thread.parkFor(Thread.java:1231) at sun.misc.Unsafe.park(Unsafe.java:323) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:159) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2019) at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:413) at java.util.concurrent.ThreadPoolExecutor... 

Log in attempt aborted inicio de Log in attempt aborted se Session.setActiveSession() porque Session.setActiveSession() se llama mientras se estaba abriendo una sesión anterior.

¿Es posible que llame Session.setActiveSession() dos veces?

Puedes probar este código. No se probó, pero en parte proviene de SessionLoginSample.

 private static Session openActiveSession(Activity activity, boolean allowLoginUI, StatusCallback callback, List<String> permissions, Bundle savedInstanceState) { OpenRequest openRequest = new OpenRequest(activity).setPermissions(permissions).setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK).setCallback(callback).setDefaultAudience(SessionDefaultAudience.FRIENDS); Session session = Session.getActiveSession(); if (session == null) { if (savedInstanceState != null) { session = Session.restoreSession(this, null, fbStatusCallback, savedInstanceState); } if (session == null) { session = new Session(this); } Session.setActiveSession(session); if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED) || allowLoginUI) { session.openForRead(openRequest); return session; } } return null; } 

Si está colgando cuando el usuario ya ha autorizado los permisos, intente comprobar los permisos y excluir el código basado en si los permisos existen. Algo como:

 if(!session.getReadPermissions.contains("friends_location"){ //restore or start the session and ask for the permission } else{ //do stuff that would happen after the permission is already granted } 

No estoy en mi estación de trabajo por lo que el método puede ser un poco fuera, pero esa es la idea general que intentaría.

Reemplace su llamada de openActiveSession con código inferior.

 new Thread() { @Override public void run() { openActiveSession(this, true, fbStatusCallback, Arrays.asList("friends_location")); } }.start(); 
  • La devolución de llamada de inicio de sesión no se activa mediante facebook-android-sdk 4
  • Evitar que Facebook Android SDK muestre la contraseña como texto sin formato
  • Gestión de sesiones de Facebook en la aplicación de Android a través de múltiples actividades con Facebook SDK 3
  • Error de la aplicación al solicitar una lista de amigos
  • La aplicación se bloquea después del primer inicio de sesión en Facebook
  • Cómo obtener APP_ID para Facebook?
  • Autorización para Android Facebook SDK 3.0
  • Visión general de plataformas de terceros o bibliotecas para Android
  • Android Facebook 4.0 SDK Cómo obtener correo electrónico, fecha de nacimiento y sexo del usuario
  • ¿Podemos cambiar la imagen del enlace (que está publicado por la aplicación android) en facebook
  • Cómo resolver las herramientas de Facebook: replace = "android: theme"?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.