

Nexus 5 でプログラムを実行すると `AsyncTask` は一回しか呼ばれなかったのですが、今度は Xperia でプログラムを実行すると
`AsyncTask` が二回呼ばれてしまいました。端末が違えば挙動がおかしくなるというバグが `AsyncTask`
にはあったりするのでしょうか？以下にソースコードを記します。ログを取ってみると、 `PostTwitter` クラスの `doInBackground()`
と、 `TwitterOAuth` クラスの`getAccessToken()` の
`doInBackground()`がそれぞれ二回呼ばれていました。つまり Twitter への投稿が二回されてしまいます。これは `AsyncTask`
の使い方が何か間違っているのでしょうか？すみませんが、宜しくお願いします。

`PostTwitter` クラス:

[code]

    public class PostTwitter extends AsyncTask<String, Void, Boolean> {
        private Activity mActivity;
        private Twitter mTwitter;
    
        public PostTwitter(Activity activity) {
            mActivity = activity;
            mTwitter = TwitterUtils.getTwitterInstance(activity.getApplicationContext());
        }
    
        public void shareTwitter() {
            if (TwitterUtils.hasAccessToken(mActivity.getApplicationContext())) {
                share(mActivity);
            } else {
                TwitterOAuth twitterOAuth = new TwitterOAuth(mActivity);
                twitterOAuth.startAuthorize();
            }
        }
    
        @Override
        protected Boolean doInBackground(String... params) {
    
            try {
                File file = new File(Environment.getExternalStorageDirectory().getPath() + "/image.png");
                StatusUpdate status = new StatusUpdate(params[0]); {
                    status.setMedia(file);
                }
                mTwitter.updateStatus(status);
                return true;
            } catch (TwitterException e) {
                e.printStackTrace();
                return false;
            }
        }
    
        @Override
        protected void onPostExecute(Boolean result) {
            if (result) {
                showToast("ツイートが完了しました！");
            } else {
                showToast("ツイートに失敗しました。。。");
            }
        }
    
        private void showToast(String text) {
            Toast.makeText(mActivity, text, Toast.LENGTH_SHORT).show();
        }
    
        public void share(Activity activity) {
            PostTwitter task = new PostTwitter(activity);
            task.execute(TwitterContents.getInstance().getmMessage());
        }
    }
    
[/code]

`TwitterOAuth` クラス:

[code]

    public class TwitterOAuth {
        private Activity mActivity;
        private String mCallbackURL;
        private Twitter mTwitter;
        private RequestToken mRequestToken;
        private String mOAuthURL;
        private String mOAuthVerifier;
    
        public TwitterOAuth(Activity activity) {
            mActivity = activity;
            mCallbackURL = activity.getString(R.string.twitter_callback_url);
            mTwitter = TwitterUtils.getTwitterInstance(activity);
        }
    
        public void startAuthorize() {
            AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
                @Override
                protected String doInBackground(Void... params) {
                    try {
                        mRequestToken = mTwitter.getOAuthRequestToken(mCallbackURL);
                        mOAuthURL = mRequestToken.getAuthorizationURL();
                        return mOAuthURL;
                    } catch (TwitterException e) {
                        e.printStackTrace();
                    }
    
                    return null;
                }
    
                @Override
                protected void onPostExecute(String url) {
                    if (url != null) {
                        showTwitterDialog();
                    } else {
                        // 失敗。。。
                    }
                }
            };
            task.execute();
        }
    
        private void getAccessToken() {
            AsyncTask<String, Void, AccessToken> task = new AsyncTask<String, Void, AccessToken>() {
                @Override
                protected AccessToken doInBackground(String... params) {
                    try {
                        return mTwitter.getOAuthAccessToken(mRequestToken, params[0]);
                    } catch (TwitterException e) {
                        e.printStackTrace();
                    }
                    return null;
                }
    
                @Override
                protected void onPostExecute(AccessToken accessToken) {
                    TwitterUtils.storeAccessToken(mActivity, accessToken);
                    PostTwitter postTwitter = new PostTwitter(mActivity);
                    postTwitter.share(mActivity);
                }
            };
            task.execute(mOAuthVerifier);
        }
    }
    
[/code]


CC BY-SA 3.0
2015-01-30T08:03:55.090
5610
2015-08-02T09:09:44.657
2015-02-03T02:44:56.020
5210
5210
question
android
Android 端末によっては、 AsyncTaskが二回呼ばれてしまう


AsyncTaskはAPI 13からバッググラウンドでの処理が並列ではなくなっているので、

仮に、端末のOSのバージョンが違って

仮に、AsyncTaskの処理が同期されてない複数回呼ばれるものだったら

二回呼ばれることがあったり、なかったりするかもしれませんね。


CC BY-SA 3.0
2015-01-30T08:22:26.923
5613
2015-01-30T08:22:26.923
7256
5610
answer


解決することができました。  
実際にはAsyncTaskとは別のところで処理がおかしくなっていました。  
そのおかしくなっていた場所がダイアログを表示させる部分で、以下のコードの`onPageStarted`や`onPageFinished`が二回呼ばれていました。調べてみると、どうやら端末によって複数回呼ばれたりすることがたまにあるみたいです。なので、`onPageFinished`の`if
(!mIsPageFinished)`のようにして一度だけ処理させることで一回のみのツイートを行うことができました。

[code]

         public void showTwitterDialog() {
            final Dialog twitterDialog = new Dialog(mActivity); {
                twitterDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
                twitterDialog.setContentView(R.layout.twitter_dialog);
                WebView webView = (WebView) twitterDialog.findViewById(R.id.twitter_webview);
                webView.loadUrl(mOAuthURL);
                webView.setWebViewClient(new WebViewClient() {
    
                    @Override
                    public void onPageStarted(WebView view, String url, Bitmap favicon) {
                        super.onPageStarted(view, url, favicon);
                    }
    
                    @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {
                        return false;
                    }
    
                    @Override
                    public void onPageFinished(WebView view, String url) {
                        super.onPageFinished(view, url);
                        if (!mIsPageFinished) {
                            if (url.contains("oauth_verifier")) {
                                Uri uri = Uri.parse(url);
                                mOAuthVerifier = uri.getQueryParameter("oauth_verifier");
                                twitterDialog.dismiss();
                                getAccessToken();
                                mIsPageFinished = true;
                            } else if (url.contains("denied")) {
                                twitterDialog.dismiss();
                            }
                        }
                    }
                });
                twitterDialog.show();
            }
        }
    
[/code]


CC BY-SA 3.0
2015-02-03T02:44:02.553
5819
2015-02-03T02:44:02.553
5210
5610
answer