2012-12-31 14 views
10

Per accedere a un utente su Facebook in un'app Android, sto cercando di utilizzare il seguente codice. Dopo che l'utente ha effettuato l'accesso, devono essere recuperate tutte le posizioni dei loro amici.Login Facebook con Android SDK 3.0 che causa ANR o non funziona affatto

Sfortunatamente, questo codice causa talvolta ANR (come riportato nella console degli sviluppatori di Google Play) e talvolta non funziona. Se rimuovo l'app all'interno di Facebook (revoca le autorizzazioni), la finestra di dialogo delle autorizzazioni viene nuovamente visualizzata al prossimo avvio dell'app Android. Ma se l'app ha già le autorizzazioni, provoca quegli ANR o semplicemente si interrompe senza successo.

Sembra che parti funzionino e che le parti siano sbagliate, vero? Il seguente codice è un modo corretto di accedere e recuperare i dati?

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); 
    } 

} 

Ho anche aggiunto hash chiave della app per Facebook, sia il debug e la produzione. Non ero sicuro di dover scrivere anche il padding =.

enter image description here

non ho potuto seguire un'esercitazione ufficiale di Facebook come non voglio utilizzare il pulsante di login SDK né io uso frammenti in Android.

Edit (7 gennaio 2013):

Dopo Hartok suggerito di sostituire session.isOpened() da state.isOpened() nel metodo di callback call(), le cose funzionano nel 50% di tutti i test viene eseguito ora. Tuttavia, ci sono alcuni problemi. In alcuni casi, tutto funziona bene, in altri casi (senza di me fare nulla di diverso), v'è il seguente errore nel 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) 

Quali sono le cause di questo errore? Problema del client o problema del server? A proposito, l'app sembra congelare (ANR).

E se provo a collegare due volte in sequenza, vedo il seguente output 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) 

Perché? Perché l'attività è ancora in esecuzione?

descrizione 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... 
+0

Hai provato questi hash con qualsiasi campione FB? – gian1200

+0

hai una traccia dello stack che puoi incollare dalla console degli sviluppatori –

+0

@ gian1200: l'autenticazione funziona, come ho descritto, quindi le chiavi dovrebbero essere a posto. È solo che ho incluso entrambi, con padding "=" e senza. – caw

risposta

3

Log in attempt aborted viene generato perché Session.setActiveSession() viene chiamato mentre una sessione precedente si stava attualmente aprendo.

È possibile che si chiami Session.setActiveSession() due volte?

Si potrebbe provare questo codice. Non è stato testato, ma proviene in parte da 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; 
} 
+0

Grazie! Posso usare quel codice senza scrivere mai dati su 'savedInstanceState', in particolare dati sulla sessione? – caw

+0

Sembra essere lo stesso con quel codice: non appena una richiesta è stata eseguita, tutte le richieste successive sono in qualche modo bloccate. L'app è nuovamente bloccata (ANR) e non riesco a chiamare di nuovo questo metodo per fare una nuova richiesta. Ma cosa causa l'ANR? Sto chiamando il metodo sopra da una nuova discussione. – caw

+0

Quali sono le altre tue richieste? – Hartok

1

Sostituire la chiamata openActiveSession con codice qui sotto.

new Thread() 
     { 

      @Override 
      public void run() 
      { 


openActiveSession(this, true, fbStatusCallback, Arrays.asList("friends_location")); 


      } 
     }.start(); 
+0

Grazie! È davvero possibile? Non è necessario chiamare 'openActiveSession()' dal thread dell'interfaccia utente? – caw

+0

usa runOnUiThread o crea un Handler sull'attività e usa i metodi handler.postDelayed o handler.post per tutte le chiamate di blocco. – android2013

+0

Ti stai riferendo al modo in cui i metodi che modificano l'interfaccia utente devono essere chiamati, giusto? Sì, semplicemente chiamando 'runOnUiThread()' nel codice sopra funzionerà. Ma ho pensato che forse il codice di Facebook (che non posso cambiare) ha bisogno di accedere all'interfaccia utente. – caw

2

Se si tratta di riagganciare quando l'utente ha già autorizzato i permessi, per provare a controllare i permessi e escluso il codice in base se esistono le autorizzazioni. Qualcosa di simile:

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 
} 

io non sono al mio posto di lavoro in modo che il metodo potrebbe essere un po 'fuori, ma questa è l'idea generale che vorrei provare.

+0

Grazie! Quando ho cercato di implementare la tua idea, non ha funzionato. Ma penso che ciò che Hartok ha suggerito sia all'incirca quello di cui stavi parlando, vero? – caw

+0

Simili. Controlla lo stato della sessione e il token di accesso. Lo farei anche io, ma controllo anche per confermare le autorizzazioni appropriate. – Wenger

Problemi correlati