Подтвердить что ты не робот

Обновлено - Android Facebook api 3.0 ошибка: не удается вызвать LoginActivity с нулевым пакетом вызовов

Я пытаюсь интегрировать приложение Android с новым фейсбуком 3.0 api, но я получаю это исключение:

java.lang.RuntimeException: невозможно возобновить работу {Dk.imu.konnekt/com.facebook.LoginActivity}: com.facebook.FacebookException: не удается вызвать LoginActivity с нулевым значением вызывающий пакет. Это может произойти, если startMode вызывающего SingleInstance.

У меня есть поиск этой ошибки, но никто другой, похоже, не использовал ее. Я предполагаю, что это потому, что я использую TabHost и TabsGroupActivities для каждой вкладки. Но я не знаю, как это решить.

Я добавил здесь соответствующий код:

public class MainTabActivity extends TabActivity {    
    public void onCreate(Bundle savedInstanteState){
        super.onCreate(savedInstanteState);
        setContentView(R.layout.tab_layout);
        TabHost tabHost = getTabHost();

        View shareTab = getLayoutInflater().inflate(R.layout.share_tab, null);
        tabHost.addTab(tabHost.newTabSpec("Share").setIndicator(shareTab)
        .setContent(new Intent(MainTabActivity.this, ShareGroupActivity.class)));

        ...
    }
}

-

public class ShareGroupActivity extends TabsGroupActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startChildActivity("ShareActivity", new Intent(this, ShareActivity.class));
    }
}

-

public class ShareActivity extends BaseActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.share);

        testFacebookConnection();
    }

    public void testFacebookConnection(){
        Session session = new Session(this);
        Session.setActiveSession(session);
        SessionState state = session.getState();

        Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);

        Session.StatusCallback statusCallback = 
            new Session.StatusCallback() {
            @Override
            public void call(Session session, SessionState state, Exception exception) {
                Toast.makeText(ShareActivity.this, "Facebook session status changed", Toast.LENGTH_SHORT).show(); 
            }
        };

        if (!session.isOpened() && !session.isClosed() && session.getState() != SessionState.OPENING) {
            OpenRequest open = new OpenRequest(this).setCallback(statusCallback);
            List<String> permission = new ArrayList<String>();
            permission.add("publish_actions");
            open.setPermissions(permission);
            session.openForPublish(open);
        } else {
            Session.openActiveSession(this, true, statusCallback);
        }
    }   

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
    }
}

Любые подсказки о том, как его решить?

Обновить 1 трассировку стека

FATAL EXCEPTION: main java.lang.RuntimeException: невозможно возобновить activity {dk.imu.konnekt/com.facebook.LoginActivity}: com.facebook.FacebookException: не удается вызвать LoginActivity с нулевым значением вызывающий пакет. Это может произойти, если startMode вызывающего SingleInstance. в android.app.ActivityThread.performResumeActivity(ActivityThread.java:2812) в android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2851) в android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2234) at android.app.ActivityThread.access $600 (ActivityThread.java:139) в android.app.ActivityThread $H.handleMessage(ActivityThread.java:1261) на android.os.Handler.dispatchMessage(Handler.java:99) android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:4945) в java.lang.reflect.Method.invokeNative(собственный метод) в java.lang.reflect.Method.invoke(Method.java:511) в com.android.internal.os.ZygoteInit $MethodAndArgsCaller.run(ZygoteInit.java:784) на com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(собственный метод), вызванный: com.facebook.FacebookException: не удается вызвать LoginActivity с нулевым значением вызывающий пакет. Это может произойти, если startMode вызывающего SingleInstance. в com.facebook.LoginActivity.onResume(LoginActivity.java:110) в android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1236) at android.app.Activity.performResume(Activity.java:4613) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2796)... еще 12

Обновление 2: Я просмотрел код и нашел реализацию startChildActivity:

public void startChildActivity(String Id, Intent intent) {     
   Window window = getLocalActivityManager().startActivity(Id,intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
   if (window != null) {
       mIdList.add(Id);
       setContentView(window.getDecorView()); 
   }    
}

Он использует флаг FLAG_ACTIVITY_CLEAR_TOP. Я попытался удалить его, но не изменил результат.

Обновление 3:

https://github.com/facebook/facebook-android-sdk/blob/master/facebook/src/com/facebook/LoginActivity.java

В коде Facebook используется

callingPackage = getCallingPackage();

и

if (callingPackage == null) {
       throw new FacebookException(NULL_CALLING_PKG_ERROR_MSG);
}

http://developer.android.com/reference/android/app/Activity.html#getCallingPackage()

Этот метод имеет примечание:

Если вызывающая деятельность не ожидает результата (то есть не используйте форму startActivityForResult (Intent, int), которая включает в себя код запроса), тогда вызывающий пакет будет иметь значение null.

В методе startChildActivity я использую getLocalActivityManager(). startActivity, в TabsGroupActivity, который расширяет ActivityGroup, для обработки действий с вкладками. http://developer.android.com/reference/android/app/LocalActivityManager.html#startActivity (java.lang.String, android.content.Intent)

Этот метод не соответствует тем, что написано в заметках. Он не ожидает результата и не использует метод startActivityForResult. Этот метод также обеспечивает нечто похожее на одномоментный запуск. Как мне изменить эту реализацию метода, чтобы она могла работать с facebook?

4b9b3361

Ответ 1

После многих поисков я понял, что, похоже, не существует метода startActivityForResult с LocalActivityManager, который используется на вкладках.

Итак, я понял, что для этого потребуется занятие, заполняющее весь экран. Активность показывается только со вторым сетевым подключением - я также сделал это с опцией republish и ошибками.

Начать публикацию:

Intent intent = new Intent(this, FacebookShareActivity.class);
intent.putExtra(Constants.FACEBOOK_MESSAGE, shareMessage.getMessage());
startActivityForResult(intent, 1);

Код активности для обмена Facebook - публикация на стене пользователей:

public class FacebookShareActivity extends Activity {
    String message;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.facebook_publishing);

        message = getIntent().getExtras().getString(Constants.FACEBOOK_MESSAGE);
        createFacebookConnection();
    }

    public void republishButton_Click(View view){
        setVisibilityForRepublishButton(false);
        createFacebookConnection();
    }

    public void createFacebookConnection() {
        Session session = new Session(this);
        Session.setActiveSession(session);

        Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);

        Session.StatusCallback statusCallback = new Session.StatusCallback() {
            @Override
            public void call(Session session, SessionState state, Exception exception) {
                String message = "Facebook session status changed - " + session.getState() + " - Exception: " + exception;
                //Toast.makeText(FacebookShareActivity.this, message, Toast.LENGTH_SHORT).show();
                Log.w("Facebook test", message);

                if (session.isOpened() || session.getPermissions().contains("publish_actions")) {
                    publishToWall();
                } else if (session.isOpened()) {
                    OpenRequest open = new OpenRequest(FacebookShareActivity.this).setCallback(this);
                    List<String> permission = new ArrayList<String>();
                    permission.add("publish_actions");
                    open.setPermissions(permission);
                    Log.w("Facebook test", "Open for publish");
                    session.openForPublish(open);
                }
            }
        };

        if (!session.isOpened() && !session.isClosed() && session.getState() != SessionState.OPENING) {
            session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
        } else {
            Log.w("Facebook test", "Open active session");
            Session.openActiveSession(this, true, statusCallback);
        }
    }

    private void setVisibilityForRepublishButton(Boolean visible) {
        ((Button) findViewById(R.id.republishButton)).setVisibility(visible ? View.VISIBLE : View.GONE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
        //Toast.makeText(FacebookShareActivity.this, "onActivityResult", Toast.LENGTH_SHORT).show();
    }

    void publishToWall() {
        Session session = Session.getActiveSession();

        Bundle postParams = new Bundle();
        postParams.putString("message", message);

        final Context context = this;
        Request.Callback callback = new Request.Callback() {
            public void onCompleted(Response response) {
                FacebookRequestError error = response.getError();
                if (error != null) {
                    setVisibilityForRepublishButton(true);
                    Toast.makeText(context, error.getErrorMessage(), Toast.LENGTH_SHORT).show();
                } else {
                    JSONObject graphResponse = response.getGraphObject().getInnerJSONObject();
                    String postId = null;
                    try {
                        postId = graphResponse.getString("id");
                    } catch (JSONException e) {
                        setVisibilityForRepublishButton(true);
                        Log.i("Facebook error", "JSON error " + e.getMessage());
                    }
                    //Toast.makeText(context, postId, Toast.LENGTH_LONG).show();
                    finish();
                }
            }
        };

        Request request = new Request(Session.getActiveSession(), "me/feed", postParams, HttpMethod.POST, callback);

        RequestAsyncTask task = new RequestAsyncTask(request);
        task.execute();
    }
}

Ответ 2

Мне удалось найти свою проблему. Хотя я не устанавливал

Android: launchMode = "singleTask"

моя LoginActivity имела

Android: noHistory = "истина"

что приводит к этому исключению. Я положил noHistory true, потому что я не хотел, чтобы пользователь мог нажать кнопку в первой активности после входа в систему и вернуться к экрану входа в систему. Теперь мне нужно найти другое решение.

Ответ 3

У меня такая же проблема: попытка войти в facebook с диалогом, представленным внутри SDK, но из активности, которая сама была внутри tabgroup; как ShareActivity выше.

То, что я сделал, в основном называется startActivityForResult для родительской активности ShareActivity (то есть ShareGroupActivity), вместо того, чтобы называть его в ShareActivity.

Итак, добавьте это в ShareGroupActivity:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    System.out.println("facebook status called");
    super.onActivityResult(requestCode, resultCode, data);
    Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}

2 вам нужно изменить сеанс класса, в рамках проекта FacebookSDK, в разделе src com.facebook

2.1 добавить булев элемент

public boolean insideTabGroup;

2.2 изменить StartActivityDelegate, который используется сеансом для открытия входа; добавить логическое значение как параметр

interface StartActivityDelegate {
    public void startActivityForResult(Intent intent, int requestCode, boolean insideTabGroup);

    public Activity getActivityContext();
}

2.3 внутри внутреннего класса AuthorizationRequest, измените реализацию этого делегата:

    AuthorizationRequest(final Activity activity) {
        startActivityDelegate = new StartActivityDelegate() {
            @Override
            public void startActivityForResult(Intent intent, int requestCode, boolean insideTabGroup) {
                if(insideTabGroup) {
                    ActivityGroup parentActivity = (ActivityGroup) activity.getParent();
                    parentActivity.startActivityForResult(intent,requestCode);

                } else {
                    activity.startActivityForResult(intent, requestCode);
                }
            }

            @Override
            public Activity getActivityContext() {
                return activity;
            }
        };
    }

2.4 Также измените другие конструкторы AuthorizationRequest, просто добавив логический параметр. Поскольку я не использую логин для facebook где-то в другом месте, чем активность, это нормально.

2.5 Модифицируйте метод tryLoginActivity класса Session, чтобы использовать логический элемент как параметр:

private boolean tryLoginActivity(AuthorizationRequest request) {
    Intent intent = getLoginActivityIntent(request);

    if (!resolveIntent(intent)) {
        return false;
    }

    try {
        request.getStartActivityDelegate().startActivityForResult(intent, request.getRequestCode(),this.insideTabGroup);

    } catch (ActivityNotFoundException e) {
        return false;
    }

    return true;
}

3 Задайте логический элемент в сеансе:

Session session = Session.getActiveSession();
session.insideTabGroup = true;

Это должно сделать трюк.

Cdt

Ответ 4

У меня была такая же ошибка с интеграцией SDK Parse.com Facebook, и мне не хватало вызова ParseFacebookUtils.finishAuthentication, который отмечен в docs.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  ParseFacebookUtils.finishAuthentication(requestCode, resultCode, data);
}