13.3.3. 重构StatusActivity
13.3.3.重构StatusActivity
StatusActivity是位置信息。同WhereAmI一样,我们仍调用LocationManager的getSystemService(),并注册到位置服务,订阅其更新。也同样实现一个LocationListener接口,也就意味着需要在Activity里面添加几个回调方法,好在位置变化时得到新的location对象。到下次更新状态的时候,即可在这里看到我们的位置信息。
例 13.8. StatusActivity.java
package com.marakana.yamba8;
import winterwell.jtwitter.Twitter;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class StatusActivity extends BaseActivity implements OnClickListener,
TextWatcher, LocationListener { //
private static final String TAG = "StatusActivity";
private static final long LOCATION_MIN_TIME = 3600000; // One hour
private static final float LOCATION_MIN_DISTANCE = 1000; // One kilometer
EditText editText;
Button updateButton;
TextView textCount;
LocationManager locationManager; //
Location location;
String provider;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.status);
// Find views
editText = (EditText) findViewById(R.id.editText);
updateButton = (Button) findViewById(R.id.buttonUpdate);
updateButton.setOnClickListener(this);
textCount = (TextView) findViewById(R.id.textCount);
textCount.setText(Integer.toString(140));
textCount.setTextColor(Color.GREEN);
editText.addTextChangedListener(this);
}
@Override
protected void onResume() {
super.onResume();
// Setup location information
provider = yamba.getProvider(); //
if (!YambaApplication.LOCATION_PROVIDER_NONE.equals(provider)) { //
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); //
}
if (locationManager != null) {
location = locationManager.getLastKnownLocation(provider); //
locationManager.requestLocationUpdates(provider, LOCATION_MIN_TIME,
LOCATION_MIN_DISTANCE, this); //
}
}
@Override
protected void onPause() {
super.onPause();
if (locationManager != null) {
locationManager.removeUpdates(this); //
}
}
// Called when button is clicked
public void onClick(View v) {
String status = editText.getText().toString();
new PostToTwitter().execute(status);
Log.d(TAG, "onClicked");
}
// Asynchronously posts to twitter
class PostToTwitter extends AsyncTask<String, Integer, String> {
// Called to initiate the background activity
@Override
protected String doInBackground(String...statuses) {
try {
// Check if we have the location
if (location != null) { //
double latlong[] = {location.getLatitude(), location.getLongitude()};
yamba.getTwitter().setMyLocation(latlong);
}
Twitter.Status status = yamba.getTwitter().updateStatus(statuses[0]);
return status.text;
} catch (RuntimeException e) {
Log.e(TAG, "Failed to connect to twitter service", e);
return "Failed to post";
}
}
// Called once the background activity has completed
@Override
protected void onPostExecute(String result) {
Toast.makeText(StatusActivity.this, result, Toast.LENGTH_LONG).show();
}
}
// TextWatcher methods
public void afterTextChanged(Editable statusText) {
int count = 140 - statusText.length();
textCount.setText(Integer.toString(count));
textCount.setTextColor(Color.GREEN);
if (count < 10)
textCount.setTextColor(Color.YELLOW);
if (count < 0)
textCount.setTextColor(Color.RED);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
// LocationListener methods
public void onLocationChanged(Location location) { //
this.location = location;
}
public void onProviderDisabled(String provider) { //
if (this.provider.equals(provider))
locationManager.removeUpdates(this);
}
public void onProviderEnabled(String provider) { //
if (this.provider.equals(provider))
locationManager.requestLocationUpdates(this.provider, LOCATION_MIN_TIME,
LOCATION_MIN_DISTANCE, this);
}
public void onStatusChanged(String provider, int status, Bundle extras) { //
}
}
- 令StatusActivity实现LocationListener,也就是供LocationManager回调的接口。
- 定义几个私有变量,分别表示LocationManager、Location对象与位置信息源(Provider)。
- 获取YambaApplication对象提供的位置信息源(Provider)。使用哪个信息源由用户在首选项中决定。
- 检查用户是否愿意发布自己的位置信息。
- 如果检查通过,就使用getSystemService()获取位置信息。这个调用只是获得现有系统服务的引用,因此它的代价并不是很高昂。
- 如果可以,获取缓存中的位置信息。
- 注册到LocationManager,订阅位置的更新。在这里,我们可以为位置变化指明一个时间间隔以及位置间距。我们只关心城市级别的位置变化,因此将间距的值定为一千米,时间间隔定为一小时(3,600,000微秒)。留意这只是给系统的一个提示,而非强制。
- 在用户发布消息时,检查当前是否有位置信息存在。如果有,就把它放在一个double类型的数组里,传给Twitter对象的setMyLocation()方法。
- 实现LocationManager触发的回调方法,onLocationChanged()。它在位置变化时触发,以一个新的Location对象作为参数。
- 这个方法在位置信息源不可用时触发。我们可以在这里注销订阅,以节约电能。
- 在位置信息源可用时,重新订阅位置信息的更新。
- 这个方法在位置信息源变化时触发,在此留空。
到这里,Yamba已经实现了位置更新的功能。用户可以设置首选项,按自己的意愿选择位置信息源,也可以关闭这个功能。
接下来看下另一个系统服务:Alarm服务,我们将通过它来触发IntentService。