0

明らかにどこかにあるはずのエラーを見つけるのに苦労しています。おそらく、私が認識していない論理エラーです。

クリックすると、自分の位置を特定する locationManager を開始するボタンがあります。現在地をスキャンしている間、ボタンを無効にしたいです。私はなんとかそれを行うことができました(Yay)が、最初に場所を取得してボタンを2回クリックした後、2回目の場所を受け取るために、ボタンはもう無効になりません. これにより、ボタンを複数回タップできるようになり、場所をリッスンする locationListener がどんどん開始されます。それは、スキャン中にボタンを無効にすることで防止しようとしたことです.

これが私のコードです。説明は次のとおりです。

主な活動:

public class MainActivity extends FragmentActivity {

// Setting layout dependent variables
...
private Button btn_scan;

// Setting several variables
...

// Setting default values
...

private boolean locationReceived = false;
private boolean gsmReceived = false;
private boolean isBusy = false;

private int counter = 0;
private Handler handler;
private Runnable runnable = new Runnable() {

    public void run() {

        counter ++;
        handler.postDelayed(runnable, 1000);

        if (locationReceived && gsmReceived) {

            // SAVE DATA TO DB HERE! //
            displayInformation();
            handler.removeCallbacks(runnable);

        } else if (counter >= (TIME_TO_WAIT_FOR_RESPONSE+1)) {

            displayInformation();
            handler.removeCallbacks(runnable);

        }
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Application context
    context = getApplicationContext();

    // Handler
    handler = new Handler();

    // initializing layout dependent variables
    ...
    btn_scan = (Button) findViewById(R.id.btn_scan);

    // Initialize GoogleMap
    ...

    // Get the LocationManager for checking, if providers are enabled
    locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    // Get the PhoneStateListener and telephony service to receive the signal strength
    myListener = new MyPhoneStateListener();
    tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

    // Ask for the current location in here.
    locationResult = new LocationResult() {

        @Override
        public void gotLocation(final Location location) {

            // If location given, do something with it. If not, return some message.
            if (location != null) {

                updateGeoData(location);

            }

        }
    };

    btn_scan.setOnClickListener(new OnClickListener(){

        @Override
        public void onClick(View v) {

            if (!isBusy) {
                toogleButton();

                // if GPS is enabled in phone settings
                if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {

                    postGPSAlert();
                    toogleButton();

                } else {

                    // If GPS enabled, get info
                    getInformation();
                }
            }
        }
    });
}

/*
 * wrapper method for getting informations
 */
private void getInformation() {

    // start informationfetcher. 
    runnable.run();
    // get geo location, longitude & latitude
    getGeoLocation();
    // get signal strength and its' other parameters
    getSignalStrength();
    // get internet connectivity quality string
    getConnectivityQuality();
    // get internet connectivity type
    getConnectivityType();
}

/*
 * get signal strength. only starts the listener, which does the rest of the job.
 */
public void getSignalStrength() {

    tel.listen(myListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}

/*
 * get connectivity type and update the variable internetType
 */
private void getConnectivityType() {

   ... nothing important
}

/*
 * Gets internet quality string
 */
private void getConnectivityQuality() {

    ... nothing important
}

/*
 * Gets the geo location
 */
public void getGeoLocation() {

    MyLocation myLocation = new MyLocation(context, TIME_TO_WAIT_FOR_RESPONSE);
    if (!myLocation.getLocation(locationResult)) {
        String message = "To make use of localization, please enable GPS or mobile networking.";
        Toast.makeText(context, message, Toast.LENGTH_LONG).show();
    }
}

/*
 * Updates retrieved GeoData
 */
private void updateGeoData(Location location) {

    latitude = location.getLatitude();
    longitude = location.getLongitude();    
    locationReceived = true;
}

/*
 * Updates GUI with all received values
 */
private void displayInformation() {

    ... only updating textViews here

    if (gsmReceived) {

        ... only updating textViews here

    }

    if (locationReceived) {

        ... only updating textViews here and moving googleMapCamera to some spot

    } 

    // Post Error messages, if location and/or GSM could not be obtained.
    ... just Toasting some error messages, if no signal or GPS received.

    toogleButton();
}

/*
 * Posts an alert saying u gotta enable GPS
 */
private void postGPSAlert() {
    // Prompt alert
    AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);

    // Title and message values
    alert.setTitle(getString(R.string.prompt_titleProviderFail));
    alert.setMessage(getString(R.string.prompt_messageProviderFail));

    // If OK was clicked, redirect to settings to enable GPS
    alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

        public void onClick(DialogInterface dialog, int whichButton) {

            startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
        }
    });

    // If ABORT was clicked, redirect back to activity
    alert.setNegativeButton("Abort", new DialogInterface.OnClickListener() {

        public void onClick(DialogInterface dialog, int whichButton) {

            // Canceled.
        }
    });

    // Show dialog
    alert.show();
}

/*
 * Method for disabling and enabling the button on pressure/update
 */
private void toogleButton() {

    if (btn_scan.isEnabled()) {

        isBusy = true;
        btn_scan.setText("SCANNING ...");
        btn_scan.setEnabled(false);
    } else if (!btn_scan.isEnabled()) {

        isBusy = false;
        btn_scan.setText("SCAN");
        btn_scan.setEnabled(true);
    }
}

/*
 * (non-Javadoc)
 * Listener, to listen on signalStrength of your phone. It'll set all the variables declared above and update the info you'll see.
 */
private class MyPhoneStateListener extends PhoneStateListener {

    @Override
    public void onSignalStrengthsChanged(SignalStrength signalStrength) {

        super.onSignalStrengthsChanged(signalStrength);

        ... just updating some String variables here

        gsmReceived = true;

        tel.listen(myListener, PhoneStateListener.LISTEN_NONE);
    }
}  

}

ボタンをクリックするとすぐに、すでに操作が実行されているかどうかを確認し、メソッドtoogleButton()を介してボタンを無効にしています。そのため、ネットワーク、signalStrength、および現在地に関する情報を収集するために、いくつかのメソッドがトリガーされます。通常、自分の位置を収集するのに最も時間がかかりますが、それは重要ではありません。すべての情報が収集された場合、ハンドラー + ランナブルを使用して毎秒 60 秒間チェックしています。その場合、userInterface のdisplayInformation()を介してすべての情報を表示し、toogleButton( )を介してボタンを再度有効にします。また、変数isBusy = trueを設定しています. すべての情報を収集せずに 60 秒が経過した場合でも、(それまで) 収集されたすべての情報を表示し、ボタンをもう一度 (有効な状態に) 押します。

これはすべて、初めて正常に機能します。すべての情報を受け取った後にもう一度ボタンを押すと、ボタンは無効になりませんが、アプリは必要に応じて情報を収集します。ここでの唯一の問題は、ボタンを複数回押して、複数の要求を開始して情報を収集できるようになったことです。それは私が望むものではありません。一つ一つ欲しい。

ここで私が何を間違えたか知っていますか?

4

2 に答える 2

1

あなたのコードは少し面倒です。toggleButton メソッドの isBusy フィールドを変更しないでください。これらのパーツを取り外して、ポジショニング プロセスの開始と終了がわかっている場所に配置します。Button.isEnabled() と isBusy の間で競合が発生し、この論理エラーが発生したと思います。

于 2013-07-06T11:12:19.877 に答える
1

Asynctaskスレッドを使用します - onPreExecute でボタンを無効にし、doInBackground()内に位置検索コードを記述し、 onPostExecude内でボタンを有効にします

于 2013-07-06T10:26:32.373 に答える