public static void init(String appID) {
    Session session;
    if (FB.isLoggedIn()) {
      session = Session.getActiveSession();
      // this shouldn't be an issue for most people: the app id in the session not matching the one
      // provided
      // instead it can probably happen if a developer wants to switch app ids at run time.
      if (appID != session.getApplicationId()) {
        Log.w(
            FB.TAG,
            "App Id in active session ("
                + session.getApplicationId()
                + ") doesn't match App Id passed in: "
                + appID);
        session = new Builder(FB.getUnityActivity()).setApplicationId(appID).build();
      }
    } else {
      session = new Builder(FB.getUnityActivity()).setApplicationId(appID).build();
    }
    Session.setActiveSession(session);

    final UnityMessage unityMessage = new UnityMessage("OnInitComplete");
    unityMessage.put("key_hash", FB.getKeyHash());

    // if there is an existing session, reopen it
    if (SessionState.CREATED_TOKEN_LOADED.equals(session.getState())) {
      Session.StatusCallback finalCallback = getFinalCallback(unityMessage, null);
      sessionOpenRequest(session, finalCallback, FB.getUnityActivity(), null, false);
    } else {
      unityMessage.send();
    }
  }
  public static void login(String params, final Activity activity) {
    Session session = Session.getActiveSession();
    if (session == null) {
      Log.w(FB.TAG, "Session not found. Call init() before calling login()");
      return;
    }
    // if the old session is closed (or login was cancelled), create new one
    if (session.isClosed()) {
      session =
          new Builder(FB.getUnityActivity()).setApplicationId(session.getApplicationId()).build();
      Session.setActiveSession(session);
    }
    final UnityMessage unityMessage = new UnityMessage("OnLoginComplete");

    unityMessage.put("key_hash", FB.getKeyHash());

    // parse and separate the permissions into read and publish permissions
    List<String> permissions = new ArrayList<String>();
    UnityParams unity_params = UnityParams.parse(params, "couldn't parse login params: " + params);
    if (unity_params.hasString("scope")) {
      permissions =
          new ArrayList<String>(Arrays.asList(unity_params.getString("scope").split(",")));
    }
    List<String> publishPermissions = new ArrayList<String>();
    List<String> readPermissions = new ArrayList<String>();
    if (permissions.size() > 0) {
      for (String s : permissions) {
        if (s.length() == 0) {
          continue;
        }
        if (Session.isPublishPermission(s)) {
          publishPermissions.add(s);
        } else {
          readPermissions.add((s));
        }
      }
    }
    boolean hasPublishPermissions = !publishPermissions.isEmpty();

    // check to see if the readPermissions have been TOSed already
    // we don't need to show the readPermissions dialog if they have all been TOSed even though it's
    // a mix
    // of permissions
    boolean showMixedPermissionsFlow =
        hasPublishPermissions && !session.getPermissions().containsAll(readPermissions);

    // if we're logging in and showing a mix of publish and read permission, we need to split up the
    // dialogs
    // first just show the read permissions, after they are accepted show publish permissions
    if (showMixedPermissionsFlow) {
      Session.StatusCallback afterReadPermissionCallback =
          getAfterReadPermissionLoginCallback(unityMessage, publishPermissions, activity);
      sessionOpenRequest(session, afterReadPermissionCallback, activity, readPermissions, false);
    } else {
      Session.StatusCallback finalCallback = getFinalCallback(unityMessage, activity);
      sessionOpenRequest(session, finalCallback, activity, permissions, hasPublishPermissions);
    }
  }