9

更新:このバグの解決にご協力いただきありがとうございます。原因はまだわかりませんが、以前のコミットにロールバックして、そこから開発を続けることができました。この以前のコミットは同じバグを示していましたが、コメントアウトした後 button.performClick()は消えました。奇妙なことに、これは最新のコミットでは機能しません。

私はまだこのバグを理解していません。根本的な原因を特定するために、さらに支援をお願いします。私の最大の恐怖は、うっかり再導入してしまうことです。


今まで見た中で最もクレイジーなエラーがあります。

OnCreate メソッドが何度も呼び出され、アプリケーションがフリーズし、ちらつきが発生します。唯一の解決策は、ホーム画面に戻り、設定メニューからアプリケーションを強制終了することです。

詳細は次のとおりです。

  1. アプリケーションの開始 (メイン アクティビティ)
  2. メイン アクティビティが 2 番目のアクティビティを呼び出す
  3. 2 番目のアクティビティは onCreate を呼び出し、通常どおりに設定します
  4. 2 番目のアクティビティはランダムに onCreate を終了することを決定します <-- これが起こっていると思います
  5. 2 番目のアクティビティの onCreate が再度呼び出されます。メイン アクティビティに戻ることはありません。

デバッガーを実行しました。2 番目のアクティビティが onComplete/onResume シーケンスを正常に完了し、終了して再起動することを決定したようです。

誰もこの行動について聞いたことがありますか?

例外がスローされていることに気づいていません。また、デバッグの過程で、サイレント フェイルとして表示される場所を確認しました。(これは、print ステートメントを散らかす前の古いコードです)

更新:プロセスを停止しようとするときは、機内モードをオンにする必要があります。これは、このコード ブロック (2 番目のアクティビティ) と関係があることを意味します。

else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId())
        {...}

インターネットがない場合、else ステートメントにヒットし、この動作は表示されません。

コード:

メイン アクティビティの onResume() で、2 番目のアクティビティを呼び出します。

    @Override
    public void onResume()
    {
        super.onResume();

        //Check If logged in, else go to login page
        Login.setContext(getApplicationContext());

        //Reset Notification Number
        GCMIntentService.cancelNotifications();

        /** GO TO LOGIN **/
        if(!Login.isLoggedIn())
        {
            //If user is not logged in, open login page
            System.out.println("RESUMING MAIN AND STARTING LOGIN INTENT");
            Intent intent = new Intent(ActivityMain.this, ActivityLogin.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

        } else
        {
            Login.setupStuffOnce();
            Event.pullEvents(); //Get New Events

            //Update ListView
            updateMainFeed();
        }


    }

これは 2 番目のアクティビティです。

public class ActivityLogin extends Activity
{

    private String postData;
    //private Context c;
    //final Timer timer = new Timer();

    //Facebook Stuff
    private Facebook facebook = new Facebook(Config.FBAPPID);
    private AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);

    //Layout Stuff
    EditText username, password;
    Button loginButton, signupButton;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        // Open Database
        Login.setContext(getApplicationContext());
        Database.open(getApplicationContext());
    }

    /*
     * @Override public void onPause() { s }
     */
    @Override
    public void onResume()
    {
        super.onResume();

        // shouldn't put here but oh well
        init();

        //If coming from ActivitySignup
        if(Transfer.username != null)
        {
            username.setText(Transfer.username);
            password.setText(Transfer.password);
            Transfer.password = null;
            Transfer.username = null;
            loginButton.performClick();
        }

    }

    public void init()
    {

        Login.getUserLoggedIn();
        if (Login.isLoggedIn())
        {
            //Do Any Additional Setup
            Login.setupStuffOnce();

            // If user is logged in, open main
            Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
            //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

        } else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId())
        {
            // Else, Make User Login
            // Inflate Login and Present Website
            String clientid = Login.getClientId();
            System.out.println("clientid:" + clientid);
            //System.exit(0);
            postData =  "mobile=1&client_id="+Login.getClientId();



            // Inflate the view
            setContentView(R.layout.activitylogin3);

            username = (EditText) findViewById(R.id.username);
            password = (EditText) findViewById(R.id.password);



            //Inflate the Button
            loginButton = (Button) findViewById(R.id.loginButton);
            signupButton = (Button) findViewById(R.id.signupButton);

            signupButton.setOnClickListener(new View.OnClickListener()
            {

                @Override
                public void onClick(View v)
                {
                    Intent intent = new Intent(ActivityLogin.this, ActivitySignup.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
                    startActivity(intent);

                }
            });

            loginButton.setOnClickListener(new View.OnClickListener() {
                  public void onClick(View view) {

                     int res = Login.sendLogin(username.getText().toString(), password.getText().toString());

                     if(res == 202)
                     {
                         //Login Successful

                         //Check if facebooked.
                         if(Login.isFacebooked())
                         {
                             //Just go to main
                             Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
                             //Are these flags necessary?
                             //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                             startActivity(intent);
                         } else
                         {
                             //Go to facebook login page
                             //Intent intent = new Intent(ActivityLogin.this, ActivityFBLogin.class);
                             //startActivity(intent);

                             //Login via Facebook
                             doFacebook();
                         }

                     } else
                     {
                         System.out.println("Login Failed: "+res);
                         if(res == 405)
                         {
                             Toast.makeText(getApplicationContext(), "Incorrect Username/Password", Toast.LENGTH_SHORT).show();
                             password.setText("");
                         }
                         else
                             Toast.makeText(getApplicationContext(), "Network Error", Toast.LENGTH_SHORT).show(); //Not entirely true in all cases i think

                     }



                      /*Login.getUserLoggedIn();
                        if(Login.isLoggedIn())
                        {
                            Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
                            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                            startActivity(intent);
                        } else {
                            Toast.makeText(getApplicationContext(), "Please Login Above", Toast.LENGTH_SHORT).show();
                        }*/
                  }
                });



        } else
        {
            // Not Logged In and No Internet Access

            setContentView(R.layout.activitylogintext);

            EditText text = (EditText) findViewById(R.id.text);
            text.setText("No Internet Connection Detected\n requires internet to login");

            Button button = (Button) findViewById(R.id.refreshButton);

            button.setOnClickListener(new View.OnClickListener() {
                  public void onClick(View view) {
                        //Login.getUserLoggedIn();
                        if(Network.haveNetworkConnection(Login.getContext()))
                        {
                            Intent intent = new Intent(ActivityLogin.this, ActivityLogin.class);
                            //intent.setFlags();
                            startActivity(intent);
                        } else {
                            Toast.makeText(getApplicationContext(), "No Internet Access Detected", Toast.LENGTH_SHORT).show();
                        }
                  }
                });

        }

    }

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

        facebook.authorizeCallback(requestCode, resultCode, data);
    }

    public void doFacebook()
    {
         facebook.authorize(this, Config.facebookPermissions, new DialogListener() {
                @Override
                public void onComplete(Bundle values) {
                     /*SharedPreferences.Editor editor = state.edit();
                     editor.putString("access_token", facebook.getAccessToken());
                     editor.putLong("access_expires", facebook.getAccessExpires());
                     editor.commit();
                        */
                     //Input into database
                     Login.saveAccessToken(facebook.getAccessToken());
                     Login.setFB(facebook.getAccessToken());
                     //Login.sendAccessToken(facebook.getAccessToken());

                     //Intent into Main Activity
                     Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
                    //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }

                @Override
                public void onFacebookError(FacebookError error) {
                    Toast.makeText(getApplicationContext(), "Error: "+error.getErrorType(), Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(DialogError e) {
                    Toast.makeText(getApplicationContext(), "Error: "+e.getMessage(), Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onCancel() {}
            });
    }

    public boolean checkForUserID(Context c)
    {
        try{
            String res = Network.getUrl("www.website.com/mobile.php?got_user=1&client_id="+Login.getClientId());
            JSONObject json = JSON.constructObject(res);
            if(JSON.handleCode(json))
            {
                if(json.getString("type").equals("userid"))
                {
                    Login.setLogin(json.getString("data"));
                    return true;
                }
            }
        } catch(Exception e)
        {
            //Silent Fail
        }
        return false;
    }


}
4

6 に答える 6

5

MainActivityお電話いただいた後、お手続きを終了していただければ問題は解決すると思いますSecondActivity。問題はおそらく、onResume再開するとすぐにイベントが発生することですMainActivity。これはMainActivity、バックグラウンドで が破壊され、再作成された可能性があるためです。別の解決策は、Activity の状態を で保存することonSaveInstanceStateです。詳しくはこちらをご覧ください。

于 2013-01-23T13:40:47.787 に答える
4

アクティビティで次のコードを確認してください。

    Button button = (Button) findViewById(R.id.refreshButton);
    button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {

                    if(Network.haveNetworkConnection(Login.getContext()))
                    {
                        Intent intent = new Intent(ActivityLogin.this, ActivityLogin.class);
                        //intent.setFlags();
                        startActivity(intent);
                    } else {
                        Toast.makeText(getApplicationContext(), "No Internet Access Detected", Toast.LENGTH_SHORT).show();
                    }
              }
            });

ここでは、ActivityLogin 自体を呼び出しています。そのため、onCreate()が何度も呼び出されています。

于 2013-01-16T06:14:48.260 に答える
2

あなたの主な問題は、ビューに戻るたびに呼び出される onResume 関数にあると思います (例: 2 番目のアクティビティを開始し、終了すると、メイン アクティビティ onResume が再度呼び出されます。2 番目のアクティビティを終了すると (または静かにクラッシュします)なんらかの理由で) mainActivity に戻り、onResume を呼び出します (サイクルが最初からやり直されます)。

どういうわけかアクティビティ 2 を終了しているかどうかはわかりませんが、確認します。

編集:また、ここにいくつかのログキャットを置きます

if (Login.isLoggedIn())
{
      //Do Any Additional Setup
      Login.setupStuffOnce();

      // If user is logged in, open main
      Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
      //intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
      Log.i("Some Tag", "Starting Main Activity From Activity 2");
      startActivity(intent);

}

上記の log.i の追加により、これがエラーの発生場所であるかどうかを知ることができ、そこから移動できます。

于 2013-01-24T21:55:46.633 に答える
2

Loginアクティビティ間で適切に共有されていない場合、ここで無限のサイクリングが発生する可能性が高く、Login.isLoggedIn()戻ってくるtrue可能性ActivityLoginがあるようfalseに思えますActivityMain

いくつかの重要な要素は、Loginオブジェクトが配置されている場所、静的かどうか、アクティビティ間でどのように参照されているかです。ActivityLogin がアクティブな間に ActivityMain が破棄される可能性は十分にあります。SharedPreferencesまたはデータベースにログイン データを格納するか、それ以外の方法で永続化することが重要です。はどのようにisLoggedIn()解決しますか (そのreturn値を決定しますか?)

提案 1: シングルトン パターンの使用を検討してください (まだ使用していない場合Login) Application。提案 3: を使用Intent.FLAG_ACTIVITY_SINGLE_TOPして、新しい ActivityMain が作成される可能性を減らすことができLoginます。これも、保存方法によっては にアクセスできない可能性があります。

活動メイン

onResume() {
    if(!Login.isLoggedIn()) {
        /* Not logged in, launch ActivityLogin! */
        Intent intent = new Intent(ActivityMain.this, ActivityLogin.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

アクティビティログイン

onResume() { /* ... */ init(); }

init() {
    Login.getUserLoggedIn();
    if (Login.isLoggedIn()) {
        /* Internet - launch ActivityMain! */
        Intent intent = new Intent(ActivityLogin.this, ActivityMain.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // <--- suggested addition
        startActivity(intent);
    else if (Network.haveNetworkConnection(Login.getContext()) && Login.checkClientId()) {
        /* No internet, the user was unable to login. */
    }
于 2013-01-25T06:37:50.327 に答える