我正在创建一个应用程序,当您在特定位置时应显示消息。只要你保持应用程序打开,一切都运行良好。但现在我使用服务没有任何反应。甚至没有在服务中调用LocationChanged。我在设置与服务的连接时做错了吗?我想在关闭应用程序时显示消息,以便它在后台运行。我之前问了一个问题,他们告诉我使用服务。我已经实施了教程中的服务(我已经从中理解了)但是当应用程序在后台运行时它不起作用。我有点像Android的新手,我不知道为什么服务部分不适合我。我可能已经忘记了一些非常重要的事情。
这是清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.geotodo"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- Required for accessing our current location -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service android:name=".LocalService" />
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="KEY"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
我根据这个问题从服务中提供了哪些代码:Gps Location updates in android is not working
我一直试图在代码不工作时进行调试,而且显然只是&#34; Bound&#34;得到印刷。我希望其他印刷品陈述也可以得到满足。
logcat的输出只是标准输出,它不会给出任何错误或类似的错误。
到目前为止,这是我的代码:
public class MainActivity extends ActionBarActivity implements SensorEventListener {
private boolean notificationEntered; /* A boolean to check if a notification is entered before we check the range and stuff like that */
private int notificationID;
/* Sensors for handling the shake gesture */
private SensorManager senSensorManager;
private Sensor senAccelerometer;
/* Variables to deal with the shake gesture */
private long lastUpdate = 0;
private float last_x, last_y, last_z;
private static final int SHAKE_THRESHOLD = 600;
/* The locationclient */
private LocationClient locationClient;
Location currentLocation;
private double currentLocationX; /* The currentLocation in meters for X value */
private double currentLocationY; /* The currentLocation in meters for Y value */
/* The todo message save button */
private Button todoSaveButton;
/* The location that will be entered by the user, the location where the notification needs to pop up */
private LatLng location;
private double locationX; /* The location in meters for X value */
private double locationY; /* The location in meters for Y value */
private GoogleMap mMap;
private LocalService service;
private boolean isBound = false;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
System.out.println("TESTJE");
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
service = (IBinder) ((LocalService.LocalBinder)service).getService();
System.out.println("TEST CONNECTIEE");
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
service = null;
}
};
void doBindService() {
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
System.out.println("BOUND");
getApplicationContext().bindService(new Intent(this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE);
isBound = true;
}
void doUnbindService() {
if (isBound) {
// Detach our existing connection.
unbindService(mConnection);
isBound = false;
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
doBindService();
senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
senSensorManager.registerListener(this, senAccelerometer , SensorManager.SENSOR_DELAY_NORMAL);
notificationEntered = false;
notificationID = -1;
/* Clear earlier saved data */
clearPreferences();
getMapSafely();
if(mMap != null){
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
mMap.setOnMapClickListener(new OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
// Creating a marker
MarkerOptions markerOptions = new MarkerOptions();
// Setting the position for the marker
markerOptions.position(latLng);
// Setting the title for the marker.
// This will be displayed on taping the marker
markerOptions.title(latLng.latitude + " : " + latLng.longitude);
// Clears the previously touched position
mMap.clear();
// Animating to the touched position
mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
// Placing a marker on the touched position
mMap.addMarker(markerOptions);
location = latLng;
}
});
todoSaveButton = (Button) findViewById(R.id.button_todo);
todoSaveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
EditText todoMessage = (EditText) findViewById(R.id.todo_message);
EditText range = (EditText) findViewById(R.id.range);
clearPreferences(); /* Delete the earlier doto messages because it's easier for this beginner app */
SharedPreferences.Editor editor = sharedPref.edit();
/* Save the todo message as a string */
if (todoMessage.getText().toString() != null) {
editor.putString("todomessage", todoMessage.getText().toString());
/* Save the range as an integer */
if (range.getText().toString() != null) {
editor.putInt("range", Integer.parseInt(range.getText().toString()));
/* Save the location in two parts latitude & longitude */
if (location != null) {
editor.putFloat("longitude", (float) location.longitude);
editor.putFloat("latitude", (float) location.latitude);
editor.commit();
notificationEntered = true;
/* Show a pop up on the phone that everything is saved */
Context context = getApplicationContext();
CharSequence text = "Todo message & location saved.";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
}
}
clearScreen();
/* The output of the entered stuff -> works!
SharedPreferences readPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
String todo = readPref.getString("todomessage", "Error");
System.out.println(todo);
int rangeOutput = readPref.getInt("range", 0);
System.out.println(rangeOutput);
String LatLng = readPref.getString("location", "Error");
System.out.println(LatLng);*/
}
private void clearScreen() {
mMap.clear(); /* Clear the marker from the map */
EditText todoMessage = (EditText) findViewById(R.id.todo_message);
EditText range = (EditText) findViewById(R.id.range);
todoMessage.setText("");
range.setText("");
}
});
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @SuppressLint("NewApi") private void getMapSafely() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Checks if we arrived at the location we need to be to show a notification
*/
private void checkIfArrived() {
/* The difference between the currentLocation and the location where we need to be to show the notification */
double differenceX;
double differenceY;
/* Convert degrees to meters */
currentLocationX = currentLocation.getLatitude() * 40008000 / 360;
currentLocationY = currentLocation.getLongitude() * 40075160 * Math.cos(currentLocation.getLatitude()) / 360;
/* Get the saved location */
SharedPreferences readPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
locationX = readPref.getFloat("latitude", (float) 0.0) * 40008000 / 360;
locationY = readPref.getFloat("longitude", (float) 0.0) * 40075160 * Math.cos(readPref.getFloat("latitude", (float) 0.0)) / 360;
/*Debug material
System.out.println("Loc X in degrees : " + readPref.getFloat("latitude", (float) 0.0));
System.out.println("Loc Y in degrees : " + readPref.getFloat("longitude", (float) 0.0));
System.out.println("loc X in meters " + locationX);
System.out.println("loc Y in meters " + locationY);
*/
/* Get the saved range */
int range = readPref.getInt("range", 0);
/* Get the absolute difference in meters */
differenceX = Math.abs(currentLocationX - locationX);
differenceY = Math.abs(currentLocationY - locationY);
/*Debug material
System.out.println("Diff X " + differenceX);
System.out.println("Diff Y " + differenceY);
System.out.println(range);
*/
/* If we are close enough in any range we show the notification */
if(differenceX <= range && differenceY <= range)
showNotification();
}
/**
* Show a notification with the todo message
*/
private void showNotification() {
/* Get the saved todo message */
SharedPreferences readPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
String todoMessage = readPref.getString("todomessage", "Error");
/* Show the notification */
if(todoMessage != "Error"){
NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.ic_launcher).setContentTitle("Todo message!").setContentText(todoMessage);
// Sets an ID for the notification
notificationID = 001;
// Gets an instance of the NotificationManager service
NotificationManager notifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Builds the notification and issues it.
notifyMgr.notify(notificationID, builder.build());
}
}
/**
* Delete a specific notification
*/
private void deleteNotification() {
NotificationManager notifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
/* Delete the notification we showed before with this ID */
if(notificationID != -1) /* If we have a notificationID */
notifyMgr.cancel(notificationID);
notificationID = -1; /* Reset the ID */
clearPreferences(); /* Delete the todo message because the todomessage has been shown */
}
/**
* Clear the preferences (todomessage that has been added)
*/
private void clearPreferences() {
SharedPreferences sharedPref = MainActivity.this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.clear();
editor.commit();
}
@Override
protected void onPause() {
super.onPause();
senSensorManager.unregisterListener(this);
}
@Override
protected void onResume() {
super.onResume();
senSensorManager.registerListener(this, senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
Sensor mySensor = sensorEvent.sensor;
if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
long curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 100) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;
float speed = Math.abs(x + y + z - last_x - last_y - last_z)/ diffTime * 10000;
if (speed > SHAKE_THRESHOLD) {
deleteNotification();
}
last_x = x;
last_y = y;
last_z = z;
}
}
}
public class LocalService extends Service implements LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener {
/* Global constants for getting the current location */
// Milliseconds per second
private static final int MILLISECONDS_PER_SECOND = 1000;
// Update frequency in seconds
public static final int UPDATE_INTERVAL_IN_SECONDS = 5;
// Update frequency in milliseconds
private static final long UPDATE_INTERVAL =
MILLISECONDS_PER_SECOND * UPDATE_INTERVAL_IN_SECONDS;
// The fastest update frequency, in seconds
private static final int FASTEST_INTERVAL_IN_SECONDS = 1;
// A fast frequency ceiling in milliseconds
private static final long FASTEST_INTERVAL = MILLISECONDS_PER_SECOND * FASTEST_INTERVAL_IN_SECONDS;
/* Define an object that holds accuracy and frequency parameters */
LocationRequest locationRequest;
/**
* Class for clients to access. Because we know this service always
* runs in the same process as its clients, we don't need to deal with
* IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
@Override
public void onCreate() {
System.out.println("ONCREATE");
/*
* Create a new location client, using the enclosing class to handle
* callbacks.
*/
locationClient = new LocationClient(this, this, this);
// Create the LocationRequest object
locationRequest = LocationRequest.create();
// Use high accuracy
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// Set the update interval to 5 seconds
locationRequest.setInterval(UPDATE_INTERVAL);
// Set the fastest update interval to 1 second
locationRequest.setFastestInterval(FASTEST_INTERVAL);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Connect the client.
locationClient.connect();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
@Override
public void onDestroy() {
}
// Define the callback method that receives location updates, will be called
// every 5 seconds
@Override
public void onLocationChanged(Location location) {
System.out.println("TEST LOCATIONNN");
/* Change the currentLocation variable to the new location we are at */
currentLocation = location;
/*
* Check if we arrived at the location we need to be to show a
* notification
*/
if (notificationEntered)
checkIfArrived();
}
@Override
public IBinder onBind(Intent intent) {
System.out.println("BOUNDED");
return mBinder;
}
// This is the object that receives interactions from clients. See
// RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
@Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
@Override
public void onConnected(Bundle arg0) {
// Display the connection status
Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
locationClient.requestLocationUpdates(locationRequest, this);
}
@Override
public void onDisconnected() {
// Display the connection status
Toast.makeText(this, "Disconnected. Please re-connect.",
Toast.LENGTH_SHORT).show();
}
@Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
}
}
请帮忙!