为什么地理围栏没有在地理围栏中没有Wi-Fi连接的情况下被触发?

时间:2016-10-25 19:18:03

标签: android google-play-services android-geofence android-gps

我正在开发一个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" );
        }
    }
}
  }

1 个答案:

答案 0 :(得分:1)

如果您的应用没有WiFi连接,请确保您拥有可靠的数据连接,以便仍能使用Geofence。

正如你所拥有的documentation已经提到的那样,

  

如果没有可靠的数据连接,则可能不会生成警报。 这是因为地理围栏服务依赖于网络位置提供商,后者又需要数据连接。

此外,如果您更喜欢关闭wifi,请使用SettingsApi确保正确配置设备的系统设置,以便进行最佳位置检测。

请同时查看提及的SettingsAPI

  

在向位置服务发出请求时,设备的系统设置可能处于阻止应用获取所需位置数据的状态。例如,可以关闭GPS或Wi-Fi扫描。

请尝试浏览指定的文档,您也可以选择查看此SO帖子中的回复 - How do I use the Android Geofencing API?。希望有所帮助!