Created
July 3, 2020 05:10
-
-
Save libindev/66a0f7dd967497f7a038ce27981abc96 to your computer and use it in GitHub Desktop.
geofencing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.BroadcastReceiver; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.widget.Toast; | |
import com.google.android.gms.awareness.fence.FenceState; | |
public class GeofenceBroadcastReceiver extends BroadcastReceiver { | |
private static final String TAG = "GeofenceBroadcastReceiv"; | |
private String ENTER = "com.example.geofencing"+"20"; | |
private String EXIT = "com.example.geofencing"+"10"; | |
private String ENTEROREXIT = "com.example.geofencing"+"30"; | |
private String IN = "com.example.geofencing"+"40"; | |
@Override | |
public void onReceive(Context context, Intent intent) { | |
FenceState fenceState = FenceState.extract(intent); | |
String key = fenceState.getFenceKey(); | |
if (key.equals(ENTER)) { | |
fenceState.getCurrentState(); | |
} else if (key.equals(EXIT)) { | |
fenceState.getCurrentState(); | |
} else if (key.equals(ENTEROREXIT)) { | |
fenceState.getCurrentState(); | |
} else if (key.equals(IN)){ | |
fenceState.getCurrentState(); | |
}else { | |
fenceState.getCurrentState(); | |
} | |
// TODO: This method is called when the BroadcastReceiver is receiving | |
// an Intent broadcast. | |
// Toast.makeText(con text, "Geofence triggered...", Toast.LENGTH_SHORT).show(); | |
// NotificationHelper notificationHelper = new NotificationHelper(context); | |
/* GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); | |
if (geofencingEvent.hasError()) { | |
Log.d(TAG, "onReceive: Error receiving geofence event..."); | |
return; | |
} | |
List<Geofence> geofenceList = geofencingEvent.getTriggeringGeofences(); | |
for (Geofence geofence: geofenceList) { | |
Log.d(TAG, "onReceive: " + geofence.getRequestId()); | |
} | |
// Location location = geofencingEvent.getTriggeringLocation(); | |
int transitionType = geofencingEvent.getGeofenceTransition(); | |
switch (transitionType) { | |
case Geofence.GEOFENCE_TRANSITION_ENTER: | |
Toast.makeText(context, "GEOFENCE_TRANSITION_ENTER", Toast.LENGTH_SHORT).show(); | |
notificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_ENTER", "", MapsActivity.class); | |
break; | |
case Geofence.GEOFENCE_TRANSITION_DWELL: | |
Toast.makeText(context, "GEOFENCE_TRANSITION_DWELL", Toast.LENGTH_SHORT).show(); | |
notificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_DWELL", "", MapsActivity.class); | |
break; | |
case Geofence.GEOFENCE_TRANSITION_EXIT: | |
Toast.makeText(context, "GEOFENCE_TRANSITION_EXIT", Toast.LENGTH_SHORT).show(); | |
notificationHelper.sendHighPriorityNotification("GEOFENCE_TRANSITION_EXIT", "", MapsActivity.class); | |
break; | |
}*/ | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.annotation.SuppressLint; | |
import android.app.PendingIntent; | |
import android.content.Context; | |
import android.content.ContextWrapper; | |
import android.content.Intent; | |
import android.util.Log; | |
import androidx.annotation.NonNull; | |
import com.google.android.gms.awareness.Awareness; | |
import com.google.android.gms.awareness.fence.AwarenessFence; | |
import com.google.android.gms.awareness.fence.DetectedActivityFence; | |
import com.google.android.gms.awareness.fence.FenceUpdateRequest; | |
import com.google.android.gms.awareness.fence.HeadphoneFence; | |
import com.google.android.gms.awareness.fence.LocationFence; | |
import com.google.android.gms.awareness.fence.TimeFence; | |
import com.google.android.gms.awareness.state.HeadphoneState; | |
import com.google.android.gms.common.api.ApiException; | |
import com.google.android.gms.location.Geofence; | |
import com.google.android.gms.location.GeofenceStatusCodes; | |
import com.google.android.gms.location.GeofencingRequest; | |
import com.google.android.gms.maps.model.LatLng; | |
import com.google.android.gms.tasks.OnFailureListener; | |
import com.google.android.gms.tasks.OnSuccessListener; | |
public class GeofenceHelper extends ContextWrapper { | |
private static final String TAG = "GeofenceHelper"; | |
PendingIntent pendingIntent; | |
private String ENTER = "com.example.geofencing"+"20"; | |
private String EXIT = "com.example.geofencing"+"10"; | |
private String ENTEROREXIT = "com.example.geofencing"+"30"; | |
private String IN = "com.example.geofencing"+"40"; | |
public GeofenceHelper(Context base) { | |
super(base); | |
} | |
public GeofencingRequest getGeofencingRequest(Geofence geofence) { | |
return new GeofencingRequest.Builder() | |
.addGeofence(geofence) | |
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) | |
.build(); | |
} | |
@SuppressLint("MissingPermission") | |
public void getGeofence(LatLng latLng, double radius) { | |
/*new Geofence.Builder() | |
.setCircularRegion(latLng.latitude, latLng.longitude, radius) | |
.setRequestId(ID) | |
.setTransitionTypes(transitionTypes) | |
.setLoiteringDelay(5000) | |
.setExpirationDuration(Geofence.NEVER_EXPIRE) | |
.build();?/*/ | |
// AwarenessFence walkingFence = DetectedActivityFence.during(DetectedActivityFence.STILL); | |
// AwarenessFence headphoneFence = HeadphoneFence.during(HeadphoneState.PLUGGED_IN); | |
AwarenessFence locationFenceEnter = LocationFence.entering(latLng.latitude,latLng.longitude,radius); | |
AwarenessFence locationFenceExit = LocationFence.exiting(latLng.latitude,latLng.longitude,radius); | |
AwarenessFence in = LocationFence.in(latLng.latitude,latLng.longitude,radius,3*60); | |
AwarenessFence or = AwarenessFence.and(locationFenceEnter, locationFenceExit); | |
// Create a combination fence to AND primitive fences. | |
// return LocationFence.entering(latLng.latitude,latLng.longitude,radius); | |
/* geofencingClient.addGeofences(geofencingRequest, pendingIntent) | |
.addOnSuccessListener( new OnSuccessListener<Void>() { | |
@Override | |
public void onSuccess(Void aVoid) { | |
Log.d(TAG, "onSuccess: Geofence Added..."); | |
} | |
}) | |
.addOnFailureListener(new OnFailureListener() { | |
@Override | |
public void onFailure(@NonNull Exception e) { | |
String errorMessage = geofenceHelper.getErrorString(e); | |
Log.d(TAG, "onFailure: " + errorMessage); | |
} | |
});*/ | |
// AwarenessFence geofence = geofenceHelper.getGeofence(GEOFENCE_ID, latLng, radius, Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT); | |
// GeofencingRequest geofencingRequest = geofenceHelper.getGeofencingRequest(geofence); | |
// PendingIntent pendingIntent = geofenceHelper.getPendingIntent(); | |
Awareness.getFenceClient(this).updateFences(new FenceUpdateRequest.Builder() | |
// .addFence(ENTER,in, getPendingIntent()) | |
//.addFence(EXIT,locationFenceExit, getPendingIntent()) | |
.addFence(IN,in,getPendingIntent()) | |
.build()) | |
.addOnSuccessListener(new OnSuccessListener<Void>() { | |
@Override | |
public void onSuccess(Void aVoid) { | |
Log.i(TAG, "Fence was successfully registered."); | |
} | |
}) | |
.addOnFailureListener(new OnFailureListener() { | |
@Override | |
public void onFailure(@NonNull Exception e) { | |
Log.e(TAG, "Fence could not be registered: " + e); | |
} | |
}); | |
} | |
public PendingIntent getPendingIntent() { | |
if (pendingIntent != null) { | |
return pendingIntent; | |
} | |
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class); | |
pendingIntent = PendingIntent.getBroadcast(this, 2607, intent, PendingIntent.FLAG_UPDATE_CURRENT); | |
return pendingIntent; | |
} | |
public String getErrorString(Exception e) { | |
if (e instanceof ApiException) { | |
ApiException apiException = (ApiException) e; | |
switch (apiException.getStatusCode()) { | |
case GeofenceStatusCodes | |
.GEOFENCE_NOT_AVAILABLE: | |
return "GEOFENCE_NOT_AVAILABLE"; | |
case GeofenceStatusCodes | |
.GEOFENCE_TOO_MANY_GEOFENCES: | |
return "GEOFENCE_TOO_MANY_GEOFENCES"; | |
case GeofenceStatusCodes | |
.GEOFENCE_TOO_MANY_PENDING_INTENTS: | |
return "GEOFENCE_TOO_MANY_PENDING_INTENTS"; | |
} | |
} | |
return e.getLocalizedMessage(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.graphics.Typeface; | |
import android.os.Bundle; | |
import android.text.Editable; | |
import android.text.TextWatcher; | |
import android.view.Gravity; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.ScrollView; | |
import androidx.fragment.app.Fragment; | |
/** | |
* Simple fragment which contains a LogView and uses is to output log data it receives to the screen. | |
*/ | |
public class LogFragment extends Fragment { | |
private LogView mLogView; | |
private ScrollView mScrollView; | |
public LogFragment() {} | |
public View inflateViews() { | |
mScrollView = new ScrollView(getActivity()); | |
ViewGroup.LayoutParams scrollParams = new ViewGroup.LayoutParams( | |
ViewGroup.LayoutParams.MATCH_PARENT, | |
ViewGroup.LayoutParams.MATCH_PARENT); | |
mScrollView.setLayoutParams(scrollParams); | |
mLogView = new LogView(getActivity()); | |
ViewGroup.LayoutParams logParams = new ViewGroup.LayoutParams(scrollParams); | |
logParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; | |
mLogView.setLayoutParams(logParams); | |
mLogView.setClickable(true); | |
mLogView.setFocusable(true); | |
mLogView.setTypeface(Typeface.MONOSPACE); | |
// Want to set padding as 16 dips, setPadding takes pixels. Hooray math! | |
int paddingDips = 16; | |
double scale = getResources().getDisplayMetrics().density; | |
int paddingPixels = (int) ((paddingDips * (scale)) + .5); | |
mLogView.setPadding(paddingPixels, paddingPixels, paddingPixels, paddingPixels); | |
mLogView.setCompoundDrawablePadding(paddingPixels); | |
mLogView.setGravity(Gravity.BOTTOM); | |
mLogView.setTextAppearance(getActivity(), | |
android.R.style.TextAppearance_DeviceDefault_Medium); | |
mScrollView.addView(mLogView); | |
return mScrollView; | |
} | |
@Override | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, | |
Bundle savedInstanceState) { | |
View result = inflateViews(); | |
mLogView.addTextChangedListener(new TextWatcher() { | |
@Override | |
public void beforeTextChanged(CharSequence s, int start, int count, int after) {} | |
@Override | |
public void onTextChanged(CharSequence s, int start, int before, int count) {} | |
@Override | |
public void afterTextChanged(Editable s) { | |
mScrollView.fullScroll(ScrollView.FOCUS_DOWN); | |
} | |
}); | |
return result; | |
} | |
public LogView getLogView() { | |
return mLogView; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.app.Activity; | |
import android.content.Context; | |
import android.util.*; | |
import android.widget.TextView; | |
/** Simple TextView which is used to output log data. | |
*/ | |
public class LogView extends TextView { | |
public LogView(Context context) { | |
super(context); | |
} | |
public LogView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
} | |
public LogView(Context context, AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
} | |
/** | |
* Formats the log data and prints it out to the LogView. | |
* @param msg The actual message to be logged. The actual message to be logged. | |
*/ | |
public void println(final String msg) { | |
// In case this was originally called from an AsyncTask or some other off-UI thread, | |
// make sure the update occurs within the UI thread. | |
((Activity) getContext()).runOnUiThread( (new Thread(new Runnable() { | |
@Override | |
public void run() { | |
// Display the text we just generated within the LogView. | |
appendToLog(msg); | |
} | |
}))); | |
} | |
/** Outputs the string as a new line of log data in the LogView. */ | |
public void appendToLog(String s) { | |
append("\n" + s); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.annotation.NonNull; | |
import androidx.core.app.ActivityCompat; | |
import androidx.core.content.ContextCompat; | |
import androidx.fragment.app.FragmentActivity; | |
import android.Manifest; | |
import android.annotation.SuppressLint; | |
import android.app.PendingIntent; | |
import android.content.pm.PackageManager; | |
import android.graphics.Color; | |
import android.os.Build; | |
import android.os.Bundle; | |
import android.util.Log; | |
import android.widget.Toast; | |
import com.google.android.gms.awareness.Awareness; | |
import com.google.android.gms.awareness.fence.AwarenessFence; | |
import com.google.android.gms.awareness.fence.FenceUpdateRequest; | |
import com.google.android.gms.awareness.snapshot.DetectedActivityResponse; | |
import com.google.android.gms.location.ActivityRecognitionResult; | |
import com.google.android.gms.location.DetectedActivity; | |
import com.google.android.gms.location.Geofence; | |
import com.google.android.gms.location.GeofencingClient; | |
import com.google.android.gms.location.GeofencingRequest; | |
import com.google.android.gms.location.LocationServices; | |
import com.google.android.gms.maps.CameraUpdateFactory; | |
import com.google.android.gms.maps.GoogleMap; | |
import com.google.android.gms.maps.OnMapReadyCallback; | |
import com.google.android.gms.maps.SupportMapFragment; | |
import com.google.android.gms.maps.model.CircleOptions; | |
import com.google.android.gms.maps.model.LatLng; | |
import com.google.android.gms.maps.model.MarkerOptions; | |
import com.google.android.gms.tasks.OnFailureListener; | |
import com.google.android.gms.tasks.OnSuccessListener; | |
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMapLongClickListener { | |
private static final String TAG = "MapsActivity"; | |
private GoogleMap mMap; | |
private GeofencingClient geofencingClient; | |
private GeofenceHelper geofenceHelper; | |
private float GEOFENCE_RADIUS = 200; | |
private String GEOFENCE_ID = "com.example.geofencing"+"20"; | |
private int FINE_LOCATION_ACCESS_REQUEST_CODE = 10001; | |
private int BACKGROUND_LOCATION_ACCESS_REQUEST_CODE = 10002; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_maps); | |
// Obtain the SupportMapFragment and get notified when the map is ready to be used. | |
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() | |
.findFragmentById(R.id.map); | |
mapFragment.getMapAsync(this); | |
// geofencingClient = LocationServices.getGeofencingClient(this); | |
geofenceHelper = new GeofenceHelper(this); | |
} | |
/** | |
* Manipulates the map once available. | |
* This callback is triggered when the map is ready to be used. | |
* This is where we can add markers or lines, add listeners or move the camera. In this case, | |
* we just add a marker near Sydney, Australia. | |
* If Google Play services is not installed on the device, the user will be prompted to install | |
* it inside the SupportMapFragment. This method will only be triggered once the user has | |
* installed Google Play services and returned to the app. | |
*/ | |
@Override | |
public void onMapReady(GoogleMap googleMap) { | |
mMap = googleMap; | |
// Add a marker in Sydney and move the camera | |
LatLng eiffel = new LatLng(48.8589, 2.29365); | |
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(eiffel, 16)); | |
enableUserLocation(); | |
mMap.setOnMapLongClickListener(this); | |
} | |
private void enableUserLocation() { | |
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { | |
mMap.setMyLocationEnabled(true); | |
} else { | |
//Ask for permission | |
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { | |
//We need to show user a dialog for displaying why the permission is needed and then ask for the permission... | |
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_ACCESS_REQUEST_CODE); | |
} else { | |
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_ACCESS_REQUEST_CODE); | |
} | |
} | |
} | |
@SuppressLint("MissingPermission") | |
@Override | |
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { | |
if (requestCode == FINE_LOCATION_ACCESS_REQUEST_CODE) { | |
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |
//We have the permission | |
mMap.setMyLocationEnabled(true); | |
} else { | |
//We do not have the permission.. | |
} | |
} | |
if (requestCode == BACKGROUND_LOCATION_ACCESS_REQUEST_CODE) { | |
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |
//We have the permission | |
Toast.makeText(this, "You can add geofences...", Toast.LENGTH_SHORT).show(); | |
} else { | |
//We do not have the permission.. | |
Toast.makeText(this, "Background location access is neccessary for geofences to trigger...", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
} | |
@Override | |
public void onMapLongClick(LatLng latLng) { | |
if (Build.VERSION.SDK_INT >= 29) { | |
//We need background permission | |
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) { | |
handleMapLongClick(latLng); | |
} else { | |
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { | |
//We show a dialog and ask for permission | |
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); | |
} else { | |
ActivityCompat.requestPermissions(this, new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION}, BACKGROUND_LOCATION_ACCESS_REQUEST_CODE); | |
} | |
} | |
} else { | |
handleMapLongClick(latLng); | |
} | |
} | |
private void handleMapLongClick(LatLng latLng) { | |
mMap.clear(); | |
addMarker(latLng); | |
addCircle(latLng, GEOFENCE_RADIUS); | |
addGeofence(latLng, GEOFENCE_RADIUS); | |
} | |
@SuppressLint("MissingPermission") | |
private void addGeofence(LatLng latLng, double radius) { | |
geofenceHelper. getGeofence(latLng,radius); | |
} | |
private void addMarker(LatLng latLng) { | |
MarkerOptions markerOptions = new MarkerOptions().position(latLng); | |
mMap.addMarker(markerOptions); | |
} | |
private void addCircle(LatLng latLng, float radius) { | |
CircleOptions circleOptions = new CircleOptions(); | |
circleOptions.center(latLng); | |
circleOptions.radius(radius); | |
circleOptions.strokeColor(Color.argb(255, 255, 0,0)); | |
circleOptions.fillColor(Color.argb(64, 255, 0,0)); | |
circleOptions.strokeWidth(4); | |
mMap.addCircle(circleOptions); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.geofencing; | |
import android.app.Notification; | |
import android.app.NotificationChannel; | |
import android.app.NotificationManager; | |
import android.app.PendingIntent; | |
import android.content.Context; | |
import android.content.ContextWrapper; | |
import android.content.Intent; | |
import android.graphics.Color; | |
import android.os.Build; | |
import androidx.annotation.RequiresApi; | |
import androidx.core.app.NotificationCompat; | |
import androidx.core.app.NotificationManagerCompat; | |
import java.util.Random; | |
public class NotificationHelper extends ContextWrapper { | |
private static final String TAG = "NotificationHelper"; | |
public NotificationHelper(Context base) { | |
super(base); | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
createChannels(); | |
} | |
} | |
private String CHANNEL_NAME = "High priority channel"; | |
private String CHANNEL_ID = "com.example.notifications" + CHANNEL_NAME; | |
@RequiresApi(api = Build.VERSION_CODES.O) | |
private void createChannels() { | |
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH); | |
notificationChannel.enableLights(true); | |
notificationChannel.enableVibration(true); | |
notificationChannel.setDescription("this is the description of the channel."); | |
notificationChannel.setLightColor(Color.RED); | |
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); | |
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); | |
manager.createNotificationChannel(notificationChannel); | |
} | |
public void sendHighPriorityNotification(String title, String body, Class activityName) { | |
Intent intent = new Intent(this, activityName); | |
PendingIntent pendingIntent = PendingIntent.getActivity(this, 267, intent, PendingIntent.FLAG_UPDATE_CURRENT); | |
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) | |
// .setContentTitle(title) | |
// .setContentText(body) | |
.setSmallIcon(R.drawable.ic_launcher_background) | |
.setPriority(NotificationCompat.PRIORITY_HIGH) | |
.setStyle(new NotificationCompat.BigTextStyle().setSummaryText("summary").setBigContentTitle(title).bigText(body)) | |
.setContentIntent(pendingIntent) | |
.setAutoCancel(true) | |
.build(); | |
NotificationManagerCompat.from(this).notify(new Random().nextInt(), notification); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment