我正在开发一个应该定期发送用户地理位置的应用程序(间隔3分钟)。我正在阅读android文档,并想知道我是否需要在我拥有的每个活动/片段上创建一个LocationListener。
我正在考虑类似于一个像“沉默线程”一样运行的观察者。与应用程序一起将数据发送到我的服务。是否有类似的东西,或者我必须在每个地方实现LocationListener?
提前感谢。
答案 0 :(得分:1)
我有一些具有相同requeriment的实现,还要记住设备在找到时可能会失去连接,因此您可能会考虑在sqlite中实现保存位置。它看起来像这样:
WakefulAlarmListener.java
import java.util.Calendar;
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.StrictMode;
import android.util.Log;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import com.commonsware.cwac.wakeful.WakefulIntentService.AlarmListener;
/*
*
*
* @see <a> href="https://github.com/commonsguy/cwac-wakeful">https://github.com/commonsguy/cwac-wakeful</a>
* @see {@link AutoSendingWakefulIntentService}
*
*/
public class WakefulAlarmListener implements AlarmListener {
@Override
public void scheduleAlarms(AlarmManager alarmManager,PendingIntent pendingIntent, Context context)
{
IOController ioController = new IOController(context);
int autoSendingFrequency = Integer.parseInt(context.getString(R.string.default_autosending_frequency));
// Este método permite que se puedan realizar operaciones de
// red en el hilo de la interfaz gráfica (El alarmlistener se ejecuta en este hilo).
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD)
{
Log.d("WakefulAlarmListener => scheduleAlarms()", "Build version: "
+ Build.VERSION.SDK_INT + " >= "
+ Build.VERSION_CODES.GINGERBREAD
+ " => setting thread policy...");
setThreadPolicy();
}
alarmManager.cancel(pendingIntent);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar
.getInstance().getTimeInMillis(), autoSendingFrequency * 1000, pendingIntent);
}
@Override
public void sendWakefulWork(Context context) {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.FROYO)
{
context.startService(new Intent(context,LocationListenerDummyService.class));
}
IOController ioController = new IOController(context);
int autoSendingFrequency = ioController.loadAutoSendingFrequency();
int lastAutoSendingFrequency = ioController.loadLastAutoSendingFrequency();
if (autoSendingFrequency != -1)
{
Log.d("sendWakefulWork()", "autoSendingFrequency=" + autoSendingFrequency);
Log.d("sendWakefulWork()","lastAutoSendingFrequency=" + lastAutoSendingFrequency);
if (autoSendingFrequency != lastAutoSendingFrequency)
{
WakefulIntentService.cancelAlarms(context);
WakefulIntentService.scheduleAlarms(this, context);
}
else
{
Log.d("sendWakefulWork()","autoSendingFrequency == lastAutoSendingFrequency");
WakefulIntentService.sendWakefulWork(context,AutoSendingWakefulIntentService.class);
}
}
else
{
WakefulIntentService.cancelAlarms(context);
WakefulIntentService.scheduleAlarms(this, context);
Log.d("sendWakefulWork()","autoSendingFrequency == -1");
}
}
/**
* Si detecta que la alarma no se lanzó en el número de milisegundos
* devuelto, entonces asume que el usuario cerró la aplicación de forma
* forzada y vuelve a programar la alarma.
*
* Consultar la documentación de la biblioteca para más información.
*
* @return Tiempo en milisegundos. En este caso es de 0 milisegundos.
*
*/
@Override
public long getMaxAge() {
return 0;
}
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
private void setThreadPolicy() {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
}
AutosendeindWakefulIntenService.java
public class AutoSendingWakefulIntentService extends WakefulIntentService {
MDRCController myMDRC;
public AutoSendingWakefulIntentService() {
super("AutoSendingWakefulIntentService");
}
@Override
protected void doWakefulWork(Intent intent) {
int timeout = Integer.parseInt((getString(R.string.autosending_timeout)));
int sampleSize = Integer.parseInt((getString(R.string.autosending_samplesize)));
boolean useNetworkLocation = Boolean.parseBoolean((getString(R.string.use_network_location_provider)));
int autoSendingTries = Integer.parseInt(getString(R.string.autosending_connection_tries));
final WifiManager wifi = (WifiManager) getSystemService(WIFI_SERVICE);
IOController myIO =new IOController(getApplicationContext());
MyLocation myLocation = new MyLocation(getApplicationContext(),timeout, sampleSize, useNetworkLocation);
Location location = null;
location = myLocation.getLocation();
sendLocationToServer(location, autoSendingTries);
sendPendingGeoEventToServerAndUpdateCollection();
verifyBatteryLevel();
}
private void sendLocationToServer(Location location, int autoSendingTries) {
IOController myIo= new IOController(getApplicationContext());
ServerResponseParser serverResponseParser = new ServerResponseParser(getApplicationContext());
SQLDataSource mySqlDataSource = new SQLDataSource(getApplicationContext());
String type;
int actioncode=0;
Log.d("AutoSendingWakefulIntentService => sendLocationToServer()","Auto Sending Tries: " + autoSendingTries);
if (location != null)
{
if (autoSendingTries > 0)
{
myIo.saveLastLocationData(location);
Log.d("AutoSendingWakefulIntentService => sendLocationToServer()",
"Latitude: " + location.getLatitude()
+ "; Longitude: " + location.getLongitude()
+ "; Accuracy: " + location.getAccuracy());
if(location.getProvider().equals(LocationManager.GPS_PROVIDER))
{
Log.d("AutoSending","GPS");
actioncode = Integer.parseInt(getApplicationContext().getResources().getString(R.string.actioncode_automatic_gps), 16);
GeoEvent myGeoEvent = new GeoEvent(location, actioncode, new DeviceInformation(getApplicationContext()).getBatteryLevel());
//FIXME sendGeoEventToServer() ;
}
else
{
if(location.getProvider().equals(LocationManager.NETWORK_PROVIDER))
{
try {
type =location.getExtras().getString("networkLocationType");
}catch(NullPointerException ex){
type ="network";
}
if(type.equalsIgnoreCase("wifi") && !myIo.loadWifiForLocation())
{
Log.d("AutoSending","wifi");
actioncode = Integer.parseInt(getApplicationContext().getResources().getString(R.string.actioncode_automatic_passive),16);
}
else
{
Log.d("AutoSending","network");
actioncode = Integer.parseInt(getApplicationContext().getResources().getString(R.string.actioncode_automatic_network),16);
}
GeoEvent myGeoEvent = new GeoEvent(location, actioncode, new DeviceInformation(getApplicationContext()).getBatteryLevel());
mySqlDataSource.InsertGeoEvent(myGeoEvent);
//FIXME sendGeoEventToServer() ;
}
else if(location.getProvider().equals(LocationManager.PASSIVE_PROVIDER))
{
actioncode = Integer.parseInt(getApplicationContext().getResources().getString(R.string.actioncode_automatic_passive),16);
//FIXME sendGeoEventToServer() ;
}
}
}
else
{
Log.e("ASWIS=>sLTS()","Auto sending tries==0, Automatic location sending failed! Adding location to list...");
GeoEvent myGeoEvent = new GeoEvent(location, actioncode, new DeviceInformation(getApplicationContext()).getBatteryLevel());
mySqlDataSource.InsertGeoEvent(myGeoEvent);
}
}
else
{
}
}
}
和清单中的警报:
<receiver
android:name="com.commonsware.cwac.wakeful.AlarmReceiver"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.BATTERY_OKAY" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
</intent-filter>
<meta-data
android:name="com.commonsware.cwac.wakeful"
android:resource="@xml/wakeful" />
</receiver>