我正在开发一个Android应用程序,它使用gms播放服务geofencing API在用户输入地理围栏时将一些数据发送到服务器。该应用程序适用于有wifi连接的地理围栏。我的意图服务没有开始没有wifi连接的地理围栏即使在这个地理围栏中固定位置(我使用同一设备上的地图应用程序检查它)。 我认为这个问题与地理围栏半径无关,因为我测试了300米(它说100-150在文档中效果很好)。 在developer.android.com中它表示"启用Wi-Fi可以显着提高定位精度,因此如果关闭Wi-Fi,您的应用程序可能永远不会获得地理围栏警报,具体取决于几个设置,包括地理围栏的半径,设备型号或Android版本。"。我使用symphony v75作为测试设备,android版本是marshmallow。这与它有什么关系。 如果有人遇到类似的问题,请帮助。 这是我创建地理围栏的服务。
public class sendLocation extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<Status> {
dbCreate dbcreate;
SQLiteDatabase db;
private String empId;
public static final float GEOFENCE_RADIUS_IN_METERS = 300;
protected ArrayList<Geofence> mGeofenceList;
protected GoogleApiClient mGoogleApiClient;
public static final HashMap<String, LatLng> LANDMARKS = new HashMap<String, LatLng>();
private ScheduledExecutorService scheduledExecutorService;
private String logUrl="https://abdulhalim.pythonanywhere.com/rams/default/get_att_log.json";
//private String logUrl="https://rumytechnologies.com/ramsm/default/get_att_log.json";
public String Tag="newtag";
private boolean myDeletePermission=false;
dbUnitSuper dbunit;
public String unitUri="https://abdulhalim.pythonanywhere.com/rams/default/getUnits.json?client_id=";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
//buildGoogleApiClient();
mGoogleApiClient=new GoogleApiClient.Builder(getApplicationContext())
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
//dbcreate=dbCreate.getInstance(this);
dbunit=dbUnitSuper.getInstance(sendLocation.this);
empId=dbunit.readEmpId();
mGeofenceList = new ArrayList<Geofence>();
populateGeofenceList();
Log.d(Tag,"populate geofencelist is called on oncreate of service");
scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleWithFixedDelay(startSend,3,3, TimeUnit.MINUTES);
}
Runnable startSend=new Runnable() {
@Override
public void run() {
Log.d(Tag,"runnable is running");
//String[] projection={dbcreate.UNITID};
//Cursor C=db.query(dbcreate.TB_name,projection,null,null,null,null,null);
ArrayList<String> unitIds=new ArrayList<>();
dbBufferSuper dbBuffer=dbBufferSuper.getInstance(sendLocation.this);
unitIds=dbunit.readUnitIds();
if(isOnLine())
{ for(int i=0;i<unitIds.size();i++) {
String loopUnitID = unitIds.get(i);
JSONObject unitJson = dbBuffer.readBufferLog(loopUnitID);
if (unitJson != null) {
sendLog send = new sendLog();
send.execute(unitJson);
} else {
Log.d(Tag, "unitjson returns null for unit "+i);
}
}
getUnitUpdate unitUpdate=new getUnitUpdate();
unitUpdate.execute(empId);}
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!mGoogleApiClient.isConnecting() || !mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mGoogleApiClient.isConnecting() || mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
protected boolean isOnLine()
{
ConnectivityManager cm= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo=cm.getActiveNetworkInfo();
if(netInfo!=null&& netInfo.isConnectedOrConnecting())
{
return true;
}
else
{
return false;
}
}
public void populateLandmark(){
dbUnitSuper dbunit=dbUnitSuper.getInstance(this);
ArrayList<ArrayList<String>> unitInfo=dbunit.readUnitInformation();
if(unitInfo!=null) {
for(int i=0;i<unitInfo.size();i++)
{
ArrayList<String> singleUnit=unitInfo.get(i);
LANDMARKS.put(singleUnit.get(0),
new LatLng(Float.parseFloat(singleUnit.get(1)), Float.parseFloat(singleUnit.get(2))));}
}
}
public void populateGeofenceList() {
populateLandmark();
for (Map.Entry<String, LatLng> entry : LANDMARKS.entrySet()) {
mGeofenceList.add(new Geofence.Builder()
.setRequestId(entry.getKey())
.setCircularRegion(
entry.getValue().latitude,
entry.getValue().longitude,
GEOFENCE_RADIUS_IN_METERS
)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setLoiteringDelay(15000)
.setNotificationResponsiveness(30000)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_DWELL)
.build());
}
int i=mGeofenceList.size();
Log.d(Tag,"number of geofences entered in the geofence list is "+i);
}
@Override
public void onConnected(@Nullable Bundle bundle) {
try {
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
Log.d(Tag," securityException occured while adding in onconnected");
}
}
@Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL);
builder.addGeofences(mGeofenceList);
return builder.build();
}
private PendingIntent getGeofencePendingIntent() {
Intent intent = new Intent(sendLocation.this, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling addgeoFences()
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public void onResult(@NonNull Status status) {
}
private class pollTask extends AsyncTask<String,Void,String>{
@Override
protected String doInBackground(String... params) {
return null;
}
}
private class getUnitUpdate extends AsyncTask<String,Void,String> implements ResultCallback<Status> {
HttpsURLConnection https;
@Override
protected String doInBackground(String... params) {
InputStreamReader inputStream = null;
BufferedReader reader = null;
StringBuilder newSb=new StringBuilder();
newSb.append(unitUri);
newSb.append(params[0]);
try {
URL url=new URL(newSb.toString());
https=(HttpsURLConnection) url.openConnection();
if(https==null)
{Log.d(Tag,"urlconnection returns null");}
https.setRequestMethod("GET");
https.setDoInput(true);
int status =https.getResponseCode();
Log.d(Tag, "getunits Status : " + status);
inputStream = new InputStreamReader(https.getInputStream());
reader = new BufferedReader(inputStream);
StringBuilder message = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
message.append(line);
}
return message.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
https.disconnect();
}
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Log.d(Tag," updated units are"+s);
try {
JSONObject jsonRootObject=new JSONObject(s);
JSONArray jsonlatArray=jsonRootObject.optJSONArray("Latitude");
JSONArray jsonlonArray=jsonRootObject.optJSONArray("Longitude");
JSONArray jsonuniArray=jsonRootObject.optJSONArray("Unit_Id");
dbUnitSuper unitSuper=dbUnitSuper.getInstance(sendLocation.this);
ArrayList<String> unitIds=unitSuper.readUnitIds();
if(jsonuniArray.length()!=unitIds.size()){
//String empId= unitSuper.readEmpId();
//delete the rows in unit database
int del= unitSuper.deleteAllUnitInfo();
Log.d(Tag,"number of deleted unit rows are"+del);
//populate the unit database again
for(int i=0;i<jsonlatArray.length();i++){
String unit_id=jsonuniArray.getString(i);
String latitude=jsonlatArray.getString(i);
String longitude=jsonlonArray.getString(i);
long intest= unitSuper.insertData(empId,unit_id,latitude,longitude);
if(intest<0){
// Toast.makeText(MainActivity.this, "insert unsuccessful", Toast.LENGTH_LONG).show();
String rt=Integer.toString(i);
Log.d(Tag,"insert unsuccessful "+rt);
}
else{
// Toast.makeText(MainActivity.this, "successfully inserted a row", Toast.LENGTH_LONG).show();
String rt=Integer.toString(i);
Log.d(Tag,"successfully inserted a row "+rt);
}
}
/*remove geofences here
removeGeofences();
//clear mgeofencelist arraylist
if(mGeofenceList.size()>0){
mGeofenceList.clear();
}
//recreate the geofences
populateGeofenceList();*/
}else{
Log.d(Tag,"no new units are added or deleted");
}
} catch (JSONException e) {
e.printStackTrace();
}
/*if (!mGoogleApiClient.isConnecting() || !mGoogleApiClient.isConnected()) {
Log.d(Tag," entered the if block to recreate the geofences");
mGoogleApiClient.connect();
}
else {
Log.d(Tag," entered the else block to recreate the geofences");
try {
Log.d(Tag," entered the try block to recreate the geofences");
LocationServices.GeofencingApi.addGeofences(
mGoogleApiClient,
getGeofencingRequest(),
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
} catch (SecurityException securityException) {
// Catch exception generated if the app does not use ACCESS_FINE_LOCATION permission.
Log.d(Tag,"sequrity exception occured at unit updaate while creating neew geofences");
}
}*/
}
@Override
public void onResult(@NonNull com.google.android.gms.common.api.Status status) {
Log.d(Tag,"geofences recreated successfully");
}
}
private void removeGeofences(){
LocationServices.GeofencingApi.removeGeofences(
mGoogleApiClient,
// This is the same pending intent that was used in addGeofences().
getGeofencePendingIntent()
).setResultCallback(this); // Result processed in onResult().
}
private class sendLog extends AsyncTask<JSONObject,Void,String>{
HttpsURLConnection https;
String loopUnitID;
@Override
protected String doInBackground(JSONObject... params) {
InputStreamReader inputStream = null;
BufferedReader reader = null;
JSONObject parseUnitIdJson=params[0];
JSONObject rows=parseUnitIdJson.optJSONObject("Row");
loopUnitID=rows.optString("unit_id");
Log.d(Tag,"the unit id parsed in sendlog is "+loopUnitID);
String postStr=String.format(params[0].toString());
try {
URL url=new URL(logUrl);
https=(HttpsURLConnection) url.openConnection();
https.setRequestMethod("POST");
https.setDoInput(true);
https.setDoOutput(true);
OutputStreamWriter writer=new OutputStreamWriter(https.getOutputStream());
writer.write(postStr);
writer.flush();
Log.d(Tag,"data flushed succesfully");
int status =https.getResponseCode();
Log.d(Tag, "Status : " + status);
inputStream = new InputStreamReader(https.getInputStream());
reader = new BufferedReader(inputStream);
StringBuilder message = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
message.append(line);
}
Log.d(Tag,"sendLog returns"+message.toString());
return message.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
https.disconnect();
}
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
dbBufferSuper dbBuffer=dbBufferSuper.getInstance(sendLocation.this);
JSONObject sendResult=new JSONObject(s);
JSONArray suck=sendResult.optJSONArray("result");
Log.d(Tag,"the value read from result is "+suck.get(0));
if(suck.get(0).equals("success")){
Log.d(Tag,"permission granted for deleting a units log i");
int status= dbBuffer.deleteRows(loopUnitID);
if(status>0){
Log.d(Tag,"the number of affected rows in deletebufferrows is "+status);
}
// myDeletePermission=false;
/*myDeletePermission=true;
if(myDeletePermission==true){
Log.d(Tag,"delete permission is set to true");
}else{
Log.d(Tag,"delete permission is still false after getting success");
}*/
}else {Log.d(Tag,"success is not extracted properly from the json response of sendlog");}
} catch (JSONException e) {
e.printStackTrace();
Log.d(Tag,"failed to instantiate getattlogs response as json" );
}
}
}
}
答案 0 :(得分:1)
如果您的应用没有WiFi连接,请确保您拥有可靠的数据连接,以便仍能使用Geofence。
正如你所拥有的documentation已经提到的那样,
如果没有可靠的数据连接,则可能不会生成警报。 这是因为地理围栏服务依赖于网络位置提供商,后者又需要数据连接。
此外,如果您更喜欢关闭wifi,请使用SettingsApi确保正确配置设备的系统设置,以便进行最佳位置检测。
请同时查看提及的SettingsAPI,
在向位置服务发出请求时,设备的系统设置可能处于阻止应用获取所需位置数据的状态。例如,可以关闭GPS或Wi-Fi扫描。
请尝试浏览指定的文档,您也可以选择查看此SO帖子中的回复 - How do I use the Android Geofencing API?。希望有所帮助!