0

так им запустить этот образец приложение я получил на GitHub, который имеет дело с картами Google и гео заборов: https://github.com/androidfu/GeofenceExampleКак решить ошибку geofence mock_location?

И когда я запускаю код, я получаю эту ошибку: Caused by: java.lang.SecurityException: com.androidfu.example.geofences from uid 10170 not allowed to perform MOCK_LOCATION

Вот код для класса с последующим по трассе стека. Надеюсь, вы, ребята, можете дать мне некоторое представление. Также у меня есть ложное расположение в манифесте. Ошибка исходит от метода onResume().

public class MapsActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener, ResultCallback<Status> { 

     public static final String TAG = MapsActivity.class.getSimpleName(); 

     private static final long LOCATION_ITERATION_PAUSE_TIME = 1000; 
     private static final int NUMBER_OF_LOCATION_ITERATIONS = 10; 

     private GoogleMap googleMap; // Might be null if Google Play services APK is not available. 
     private MyPlaces happyPlace; 
     private MyPlaces home; 
     private List<Geofence> myFences = new ArrayList<>(); 
     private GoogleApiClient googleApiClient; 
     private PendingIntent geofencePendingIntent; 
     private UpdateLocationRunnable updateLocationRunnable; 
     private LocationManager locationManager; 
     private int marker = 0; 
     private Location lastLocation; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_maps); 

      ImageButton happyPlaceBtn = (ImageButton) findViewById(R.id.ib_happy_place); 
      happyPlaceBtn.setOnClickListener(this); 

      ImageButton homeBtn = (ImageButton) findViewById(R.id.ib_home); 
      homeBtn.setOnClickListener(this); 

      ImageButton resetBtn = (ImageButton) findViewById(R.id.ib_reset); 
      resetBtn.setOnClickListener(this); 

      setUpMapIfNeeded(); 
     } 

     /** 
     * Called when a view has been clicked. 
     * 
     * @param v The view that was clicked. 
     */ 
     @Override 
     public void onClick(View v) { 

      MyPlaces place; 
      switch (v.getId()) { 
       case R.id.ib_happy_place: 
        Toast.makeText(this, "You Clicked Happy Place", Toast.LENGTH_SHORT).show(); 
        place = happyPlace; 
        moveToLocation(place); 
        break; 
       case R.id.ib_home: 
        Toast.makeText(this, "You Clicked Home", Toast.LENGTH_SHORT).show(); 
        place = home; 
        moveToLocation(place); 
        break; 
       case R.id.ib_reset: 
        Toast.makeText(this, "Resetting Our Map", Toast.LENGTH_SHORT).show(); 
        if (updateLocationRunnable != null) { 
         updateLocationRunnable.interrupt(); 
        } 
        googleApiClient.disconnect(); 
        googleMap.clear(); 
        myFences.clear(); 
        setUpMap(); 
        break; 
      } 
     } 

     @Override 
     protected void onResume() { 
      super.onResume(); 

      setUpMapIfNeeded(); 

      this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

      Log.i(TAG, "Setup MOCK Location Providers"); 
      locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); 

      Log.i(TAG, "GPS Provider"); 
      locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, true, false, false, false, false, false, Criteria.POWER_HIGH, Criteria.ACCURACY_FINE); 
      locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true); 

      Log.i(TAG, "Network Provider"); 
      locationManager.addTestProvider(LocationManager.NETWORK_PROVIDER, true, false, true, false, false, false, false, Criteria.POWER_MEDIUM, Criteria.ACCURACY_FINE); 
      locationManager.setTestProviderEnabled(LocationManager.NETWORK_PROVIDER, true); 
     } 

     @Override 
     protected void onPause() { 
      this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

      // Interrupt our runnable if we're going into the background or exiting 
      if (updateLocationRunnable != null) { 
       updateLocationRunnable.interrupt(); 
      } 

      Log.i(TAG, "Cleanup Our Fields"); 
      locationManager.removeTestProvider(LocationManager.GPS_PROVIDER); 
      locationManager.removeTestProvider(LocationManager.NETWORK_PROVIDER); 
      locationManager = null; 
      updateLocationRunnable = null; 

      super.onPause(); 
     } 

     @Override 
     protected void onStop() { 
      googleApiClient.disconnect(); 
      super.onStop(); 
     } 

     /** 
     * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly 
     * installed) and the map has not already been instantiated.. This will ensure that we only ever 
     * call {@link #setUpMap()} once when {@link #googleMap} is not null. 
     * <p/> 
     * If it isn't installed {@link SupportMapFragment} (and 
     * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to 
     * install/update the Google Play services APK on their device. 
     * <p/> 
     * A user can return to this FragmentActivity after following the prompt and correctly 
     * installing/updating/enabling the Google Play services. Since the FragmentActivity may not 
     * have been completely destroyed during this process (it is likely that it would only be 
     * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this 
     * method in {@link #onResume()} to guarantee that it will be called. 
     */ 
     private void setUpMapIfNeeded() { 
      // Do a null check to confirm that we have not already instantiated the map. 
      if (googleMap == null) { 
       // Try to obtain the map from the SupportMapFragment. 
       googleMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap(); 
       // Check if we were successful in obtaining the map. 
       if (googleMap != null) { 
        setUpMap(); 
       } 
      } 
     } 

     /** 
     * This is where we can add markers or lines, add listeners or move the camera. 
     * <p/> 
     * This should only be called once and when we are sure that {@link #googleMap} is not null. 
     */ 
     private void setUpMap() { 
      googleMap.setBuildingsEnabled(true); 

      // PRES 1 
      /* 
       1. Create a "Place" that will become a Geofence 
       2. Add a place marker on our Map 
       3. Add our place to our list of Geofences 
       4. Repeat for each place 
      */ 

      // Add a place with a Geofence 
      happyPlace = new MyPlaces("Pier @ Folly Beach", "This is my Happy Place!", new LatLng(32.652411, -79.938063), 10000, 10, R.drawable.ic_palm_tree); 
      addPlaceMarker(happyPlace); 
      addFence(happyPlace); 

      // Add a place with a Geofence 
      // Work 39.3336585, -84.3146718 
      // Home 39.2697455, -84.269921 
      home = new MyPlaces("Home", "This is where I live.", new LatLng(39.3336585, -84.3146718), 10000, 10, R.drawable.ic_home); 
      addPlaceMarker(home); 
      addFence(home); 

      // Add a place w/o a Geofence 
      MyPlaces charleston = new MyPlaces("Charleston, SC", "This is where I want to live!", new LatLng(32.8210454, -79.9704779), 0, 10, R.drawable.ic_heart); 
      addPlaceMarker(charleston); 
      addFence(charleston); 

      /* 
       After all your places have been created and markers added you can monitor your fences. 
      */ 
      monitorFences(myFences); 

      googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() { 
       @Override 
       public void onMapClick(LatLng latLng) { 

        if (updateLocationRunnable != null && updateLocationRunnable.isAlive() && !updateLocationRunnable.isInterrupted()) { 
         updateLocationRunnable.interrupt(); 
        } 
        updateLocationRunnable = new UpdateLocationRunnable(locationManager, latLng); 
        updateLocationRunnable.start(); 

        MyPlaces touchedPlace = new MyPlaces(String.format("Marker %1$d", ++marker), "", latLng, 65, 12, 0); 
        addPlaceMarker(touchedPlace); 
       } 
      }); 
     } 

     /** 
     * Add a map marker at the place specified. 
     * 
     * @param place the place to take action on 
     */ 
     private void addPlaceMarker(MyPlaces place) { 
      MarkerOptions markerOptions = new MarkerOptions(); 
      markerOptions.position(place.getCoordinates()) 
        .title(place.getTitle()); 
      if (!TextUtils.isEmpty(place.getSnippet())) { 
       markerOptions.snippet(place.getSnippet()); 
      } 
      if (place.getIconResourceId() > 0) { 
       markerOptions.icon(BitmapDescriptorFactory.fromResource(place.getIconResourceId())); 
      } 
      googleMap.addMarker(markerOptions); 
      drawGeofenceAroundTarget(place); 
     } 

     /** 
     * If our place has a fence radius greater than 0 then draw a circle around it. 
     * 
     * @param place the place to take action on 
     */ 
     private void drawGeofenceAroundTarget(MyPlaces place) { 
      if (place.getFenceRadius() <= 0) { 
       // Nothing to draw 
       return; 
      } 
      CircleOptions circleOptions = new CircleOptions(); 
      circleOptions.center(place.getCoordinates()); 
      circleOptions.fillColor(Color.argb(0x55, 0x00, 0x00, 0xff)); 
      circleOptions.strokeColor(Color.argb(0xaa, 0x00, 0x00, 0xff)); 
      circleOptions.radius(place.getFenceRadius()); 
      googleMap.addCircle(circleOptions); 
     } 

     /** 
     * Update our map's location to the place specified. 
     * 
     * @param place the place to take action on 
     */ 
     private void moveToLocation(final MyPlaces place) { 
      // Move the camera instantly to "place" with a zoom of 5. 
      if (place.getTitle().equals("Charleston, SC")) { 
       googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(place.getCoordinates(), place.getDefaultZoomLevel())); 
      } 

      // Fly to our new location and then set the correct zoom level for the given place. 
      googleMap.animateCamera(CameraUpdateFactory.newLatLng(place.getCoordinates()), new GoogleMap.CancelableCallback() { 
       @Override 
       public void onFinish() { 
        googleMap.animateCamera(CameraUpdateFactory.zoomTo(place.getDefaultZoomLevel()), 2000, null); 
       } 

       @Override 
       public void onCancel() { 
        // Nothing to see here. 
       } 
      }); 
     } 

     /** 
     * If our place has a fence radius > 0 then add it to our monitored fences. 
     * 
     * @param place the place to take action on 
     */ 
     private void addFence(MyPlaces place) { 
      if (place.getFenceRadius() <= 0) { 
       // Nothing to monitor 
       return; 
      } 
      Geofence geofence = new Geofence.Builder() 
        .setCircularRegion(place.getCoordinates().latitude, place.getCoordinates().longitude, place.getFenceRadius()) 
        .setRequestId(place.getTitle()) // every fence must have an ID 
        .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) // can also have DWELL 
        .setExpirationDuration(Geofence.NEVER_EXPIRE) // how long do we care about this geofence? 
          //.setLoiteringDelay(60000) // 1 min. 
        .build(); 
      myFences.add(geofence); 
     } 

     /** 
     * Connect our GoogleApiClient so we can begin monitoring our fences. 
     * 
     * @param fences our list of Geofences to monitor 
     */ 
     private void monitorFences(List<Geofence> fences) { 
      if (fences.isEmpty()) { 
       throw new RuntimeException("No fences to monitor. Call addPlaceMarker() First."); 
      } 
      // PRES 2 
      googleApiClient = new GoogleApiClient.Builder(this) 
        .addApi(LocationServices.API) 
        .addConnectionCallbacks(this) 
        .addOnConnectionFailedListener(this) 
        .build(); 
      googleApiClient.connect(); 
     } 

     @Override 
     public void onConnected(Bundle bundle) { 
      /* 
       TODO 
       1. Display a spinner in the progress bar while we're waiting for location 
       2. When connected & not null update map position to location 
       3. If location null try again once every 10 seconds until we get an answer or quit after x minutes 
       4. ? 
      */ 
      Toast.makeText(this, "GoogleApiClient Connected", Toast.LENGTH_SHORT).show(); 
      lastLocation = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); 
      String lastLocationMessage; 
      if (lastLocation == null) { 
       lastLocationMessage = "Last Location is NULL"; 
       moveToLocation(home); 
      } else { 
       lastLocationMessage = String.format("Last Location (%1$s, %2$s)", lastLocation.getLatitude(), lastLocation.getLongitude()); 
       moveToLocation(new MyPlaces("Last Location", "I am here.", new LatLng(lastLocation.getLatitude(), lastLocation.getLongitude()), 0, 13, 0)); 
      } 
      Toast.makeText(this, lastLocationMessage, Toast.LENGTH_SHORT).show(); 
      // PRES 3 
      geofencePendingIntent = getRequestPendingIntent(); 
      PendingResult<Status> result = LocationServices.GeofencingApi.addGeofences(googleApiClient, myFences, geofencePendingIntent); 
      result.setResultCallback(this); 
     } 

     @Override 
     public void onConnectionSuspended(int i) { 
      Toast.makeText(this, "GoogleApiClient Connection Suspended", Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onConnectionFailed(ConnectionResult connectionResult) { 
      Toast.makeText(this, "GoogleApiClient Connection Failed", Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onResult(Status status) { 
      String toastMessage; 
      // PRES 4 
      if (status.isSuccess()) { 
       toastMessage = "Success: We Are Monitoring Our Fences"; 
      } else { 
       toastMessage = "Error: We Are NOT Monitoring Our Fences"; 
      } 
      Toast.makeText(this, toastMessage, Toast.LENGTH_SHORT).show(); 
     } 

     /** 
     * Returns the current PendingIntent to the caller. 
     * 
     * @return The PendingIntent used to create the current set of geofences 
     */ 
     public PendingIntent getRequestPendingIntent() { 
      return createRequestPendingIntent(); 
     } 

     /** 
     * Get a PendingIntent to send with the request to add Geofences. Location 
     * Services issues the Intent inside this PendingIntent whenever a geofence 
     * transition occurs for the current list of geofences. 
     * 
     * @return A PendingIntent for the IntentService that handles geofence 
     * transitions. 
     */ 
     private PendingIntent createRequestPendingIntent() { 
      if (geofencePendingIntent != null) { 
       return geofencePendingIntent; 
      } else { 
       Intent intent = new Intent(this, GeofenceTransitionReceiver.class); 
       intent.setAction("geofence_transition_action"); 
       return PendingIntent.getBroadcast(this, R.id.geofence_transition_intent, intent, PendingIntent.FLAG_UPDATE_CURRENT); 
      } 
     } 


     // ///////////////////////////////////////////////////////////////////////////////////////// 
     // // UpdateLocationRunnable                // 
     // ///////////////////////////////////////////////////////////////////////////////////////// 

     private Location createMockLocation(String locationProvider, double latitude, double longitude) { 
      Location location = new Location(locationProvider); 
      location.setLatitude(latitude); 
      location.setLongitude(longitude); 
      location.setAccuracy(1.0f); 
      location.setTime(System.currentTimeMillis()); 
      /* 
       setElapsedRealtimeNanos() was added in API 17 
      */ 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 
       location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); 
      } 
      try { 
       Method locationJellyBeanFixMethod = Location.class.getMethod("makeComplete"); 
       if (locationJellyBeanFixMethod != null) { 
        locationJellyBeanFixMethod.invoke(location); 
       } 
      } catch (Exception e) { 
       // There's no action to take here. This is a fix for Jelly Bean and no reason to report a failure. 
      } 
      return location; 
     } 


     // ///////////////////////////////////////////////////////////////////////////////////////// 
     // // CreateMockLocation                 // 
     // ///////////////////////////////////////////////////////////////////////////////////////// 

     class UpdateLocationRunnable extends Thread { 

      private final LocationManager locMgr; 
      private final LatLng latlng; 
      Location mockGpsLocation; 
      Location mockNetworkLocation; 

      UpdateLocationRunnable(LocationManager locMgr, LatLng latlng) { 
       this.locMgr = locMgr; 
       this.latlng = latlng; 
      } 

      /** 
      * Starts executing the active part of the class' code. This method is 
      * called when a thread is started that has been created with a class which 
      * implements {@code Runnable}. 
      */ 
      @Override 
      public void run() { 
       try { 
        Log.i(TAG, String.format("Setting Mock Location to: %1$s, %2$s", latlng.latitude, latlng.longitude)); 
        /* 
         Location can be finicky. Iterate over our desired location every second for 
         NUMBER_OF_LOCATION_ITERATIONS seconds to help it figure out where we want it to 
         be. 
        */ 
        for (int i = 0; !isInterrupted() && i <= NUMBER_OF_LOCATION_ITERATIONS; i++) { 
         mockGpsLocation = createMockLocation(LocationManager.GPS_PROVIDER, latlng.latitude, latlng.longitude); 
         locMgr.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockGpsLocation); 
         mockNetworkLocation = createMockLocation(LocationManager.NETWORK_PROVIDER, latlng.latitude, latlng.longitude); 
         locMgr.setTestProviderLocation(LocationManager.NETWORK_PROVIDER, mockNetworkLocation); 
         Thread.sleep(LOCATION_ITERATION_PAUSE_TIME); 
        } 
       } catch (InterruptedException e) { 
        Log.i(TAG, "Interrupted."); 
        // Do nothing. We expect this to happen when location is successfully updated. 
       } finally { 
        Log.i(TAG, "Done moving location."); 
       } 
      } 
     } 
    } 

трассировки стека:

09-26 11:08:07.870 10417-10417/com.androidfu.example.geofences E/AndroidRuntime: FATAL EXCEPTION: main 
                       Process: com.androidfu.example.geofences, PID: 10417 
                       java.lang.RuntimeException: Unable to resume activity {com.androidfu.example.geofences/com.androidfu.example.geofences.GeofenceExampleLauncher}: java.lang.SecurityException: com.androidfu.example.geofences from uid 10170 not allowed to perform MOCK_LOCATION 
                        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3121) 
                        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3152) 
                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2499) 
                        at android.app.ActivityThread.access$900(ActivityThread.java:157) 
                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356) 
                        at android.os.Handler.dispatchMessage(Handler.java:102) 
                        at android.os.Looper.loop(Looper.java:148) 
                        at android.app.ActivityThread.main(ActivityThread.java:5525) 
                        at java.lang.reflect.Method.invoke(Native Method) 
                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) 
                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) 
                        Caused by: java.lang.SecurityException: com.androidfu.example.geofences from uid 10170 not allowed to perform MOCK_LOCATION 
                        at android.os.Parcel.readException(Parcel.java:1599) 
                        at android.os.Parcel.readException(Parcel.java:1552) 
                        at android.location.ILocationManager$Stub$Proxy.addTestProvider(ILocationManager.java:1096) 
                        at android.location.LocationManager.addTestProvider(LocationManager.java:1298) 
                        at com.androidfu.example.geofences.MapsActivity.onResume(MapsActivity.java:120) 
                        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258) 
                        at android.app.Activity.performResume(Activity.java:6347) 
                        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3110) 
                        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3152)  
                        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2499)  
                        at android.app.ActivityThread.access$900(ActivityThread.java:157)  
                        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)  
                        at android.os.Handler.dispatchMessage(Handler.java:102)  
                        at android.os.Looper.loop(Looper.java:148)  
                        at android.app.ActivityThread.main(ActivityThread.java:5525)  
                        at java.lang.reflect.Method.invoke(Native Method)  
                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)  
                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)  

ответ

2

Я думаю, вы не дали фиктивных местоположений из вариантов телефонов разработчиков. Он должен быть ниже Debug.

enter image description here

+0

Эй прохладный человек, который работал. Большое спасибо! – TheQ

+0

Кстати, мне было интересно, знаете ли вы, как тост, когда кто-то входит в геофенсион? У меня есть метод onHandleIntent, и когда я помещаю строку Toast кода, она не работает. У вас есть понимание? дайте мне знать, если вы хотите, чтобы я опубликовал код – TheQ

+0

Извините за мой поздний ответ. Вы уже исправили проблему с тостами? Если нет, покажите мне код, и я посмотрю. – arsena