为了在Android应用中登录用户到Facebook,我正在尝试使用以下代码。用户登录后,应该获取所有朋友的位置。
不幸的是,这段代码有时会导致ANR(如在Google Play开发者控制台中报告的),有时它只是不起作用。如果我在Facebook内部删除应用程序(撤消权限),则权限对话框将在Android应用程序的下一次启动时再次显示。但是,如果应用程序已经具有权限,则会导致那些ANR或仅退出而不成功。
看起来有些部分是工作的,有些部分是错误的,不是吗?以下代码是登录和提取数据的正确方法吗?
如果我连续尝试连接两次,我会看到以下的LogCat输出:
不幸的是,这段代码有时会导致ANR(如在Google Play开发者控制台中报告的),有时它只是不起作用。如果我在Facebook内部删除应用程序(撤消权限),则权限对话框将在Android应用程序的下一次启动时再次显示。但是,如果应用程序已经具有权限,则会导致那些ANR或仅退出而不成功。
看起来有些部分是工作的,有些部分是错误的,不是吗?以下代码是登录和提取数据的正确方法吗?
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);
}
}
我也已经在Facebook上添加了应用程序的密钥哈希,包括调试和生产。不确定填充=
是否也要写。
我无法按照Facebook的官方教程操作,因为我不使用SDK的登录按钮,也不在Android中使用片段。
编辑(2013年1月7日):
在Hartok建议在回调的call()
方法中将session.isOpened()
替换为state.isOpened()
后,现在50%的测试运行正常。尽管如此,在某些情况下,一切正常,在其他情况下(我没有做任何不同的事情),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)
什么导致了这个错误?是客户端的问题还是服务器的问题?顺便说一下,应用程序似乎在此之后冻结(ANR)。如果我连续尝试连接两次,我会看到以下的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)
为什么会这样?任务为什么还在运行?
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...
state.isOpened()
方法。它应该是相同的结果,但也许在收到回调之前SessionState
已经更新了。 - Hartok