Closed DougSteiert closed 7 years ago
In the for (XMLAttributes data : randLocs) {
loop, you seem to be using the same trace
object.
If it's true, you are overwriting existing object and then add it to the session
.
@zaki50 Hmm interesting. So my overall goal is to basically have a "temporary" trace object, in which I add Places to it with attributes according to Semantics, then I want to dump that trace object into a Session RealmList, but I want a new Trace object each loop, I don't want to keep using the old values in the Trace object, because then the mobility trace will be wrong if it includes Places from the previous iteration of the loop. Is there a more correct way to dump these trace values in?
@DougSteiert Can you show us the entire class which contains for (XMLAttributes data : randLocs) {
loop?
You really need to start making those 4 transactions per element actually be a single transaction for all elements...
@Zhuinden I am now in the process of making the "for loop" a single transaction. I do not believe making this entire class a transaction is a good idea. My reasoning is that this class is acting upon a Service of Android and continuously on, so a transaction would ALWAYS be on until the service is stopped if I make it one transaction. Below is the entire, now updated, class..almost 400 lines @zaki50
public class LocationAnonymizer implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
Context context;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
AnonymizationService anonymizationService;
private static Random rand;
private int realLocUse;
private int randIndex;
// Create manual place types to cycle through for first-round testing
private ArrayList<String> manualPlaceTypes = new ArrayList<>();
private int count = 0;
com.djsg38.locationprivacyapp.models.Location currentLoc;
Realm realm;
GenerateNearbyCities cityGen;
ArrayList<XMLAttributes> randLocs;
ArrayList<String> cityNames;
ArrayList<LatLng> cityCoords;
ConvertPlaceTypes convertPlaceTypes;
FindNearbyPlaces findNearbyPlaces;
ArrayList<PlaceAttributes> places;
List<Integer> types;
List<String> typeStrings;
Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
updateMockLocation();
Double randTime = LocationAnonymizer.rand.nextDouble() * 29000;
int time = randTime.intValue() + 1000;
// 30000 = 30s approx
if(handler != null) handler.postDelayed(this, time);
}
};
public LocationAnonymizer(Context context, AnonymizationService anonymizationService, Integer kValue) throws ExecutionException, InterruptedException {
this.context = context;
this.anonymizationService = anonymizationService;
realm = Realm.getDefaultInstance();
Session session = realm.where(Session.class).findFirst();
Trace trace = realm.where(Trace.class).findFirst();
// Add some values for manual testing
manualPlaceTypes.add("restaurant");
manualPlaceTypes.add("university");
manualPlaceTypes.add("gas_station");
manualPlaceTypes.add("movie_theater");
manualPlaceTypes.add("cafe");
manualPlaceTypes.add("health");
findNearbyPlaces = new FindNearbyPlaces();
places = new ArrayList<>();
rand = new Random();
cityGen = new GenerateNearbyCities();
randLocs = cityGen.generateLocations(kValue);
cityNames = new ArrayList<>();
cityCoords = new ArrayList<>();
int randTypeIndex;
if(!session.getMultipleTraces().isEmpty()) {
realm.beginTransaction();
session.getMultipleTraces().deleteAllFromRealm();
realm.commitTransaction();
}
// randLocs will be empty if kvalue was 1, which then causes mock locations to break
// as getting a random index on something of size 0 fails
int id = 2;
realm.beginTransaction();
for (XMLAttributes data : randLocs) {
if(!trace.getSingleTrace().isEmpty()) {
trace.getSingleTrace().clear();
}
cityNames.add(data.getName());
cityCoords.add(new LatLng(data.getLat(), data.getLng()));
//Log.i("Fake city", data.getName());
Location loc = new Location("");
loc.setLatitude(data.getLat());
loc.setLongitude(data.getLng());
randTypeIndex = rand.nextInt(manualPlaceTypes.size());
places = findNearbyPlaces.findNearbyPlaces(loc, manualPlaceTypes.get(randTypeIndex));
for(PlaceAttributes place: places) {
Semantics temp = new Semantics();
if(place.getName() != null) {
temp.setLat(place.getLat());
temp.setLng(place.getLng());
temp.setName(place.getName());
if(!realm.isClosed()) {
trace.setID(id);
trace.addNewSemanticTrace(temp);
}
}
Log.i("WHOA", temp.getName());
}
if(!trace.getSingleTrace().isEmpty()) {
if(!realm.isClosed()) {
Log.i("ID", String.valueOf(trace.getID()));
for(Semantics place : trace.getSingleTrace()) {
Log.i("Trace", place.getName());
}
session.addNewMultipleTrace(trace);
}
}
id++;
}
realm.commitTransaction();
if(!session.getMultipleTraces().isEmpty()) {
Log.i("size", String.valueOf(session.getMultipleTraces().size()));
int i=1;
for(Trace traces : session.getMultipleTraces()) {
Log.i("IDhi",String.valueOf(traces.getID()));
if(!traces.getSingleTrace().isEmpty()) {
for(Semantics place : traces.getSingleTrace()) {
if(place.getName() != null) {
Log.i("MultTraces" +i, String.valueOf(place.getName()));
}
}
}
i++;
}
}
currentLoc = new com.djsg38.locationprivacyapp.models.Location();
// real locations is potentially empty
currentLoc.setLat(session.getRealLocations().last().getLat());
currentLoc.setLong(session.getRealLocations().last().getLong());
Log.i("CurrentLoc", String.valueOf(currentLoc.getLat()) + ',' + String.valueOf(currentLoc.getLong()));
createLocationRequest();
buildGoogleApiClient();
mGoogleApiClient.connect();
}
// Initiate a timer for logging location
public void startTimer() {
Log.i("Timer", "Started");
runnable.run();
}
// Stop faking the location
public void stopMockLocs() {
handler.removeCallbacksAndMessages(null);
runnable = null;
handler = null;
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
if(mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.setMockMode(mGoogleApiClient, false);
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
realm.close();
}
// Initialize the ability to set mock locations
private void setMockLocation() {
try {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationServices.FusedLocationApi.setMockMode(mGoogleApiClient, true);
} catch (Exception e) {
e.printStackTrace();
}
}
// Update the current mocked location to a new value
private void updateMockLocation() {
randIndex = rand.nextInt(cityCoords.size());
// Don't ask, don't tell
// Just random number divisible by 3
realLocUse = rand.nextInt(51);
// Another method to ensure app doesn't go too long without using real loc
Location mockLoc = new Location(LocationManager.NETWORK_PROVIDER);
// If the number is divisible by 3, then go ahead and use the real location (random choice)
if((((realLocUse % 3) == 0) && (count > 2)) || count == 10) {
mockLoc.setLatitude(currentLoc.getLat());
mockLoc.setLongitude(currentLoc.getLong());
Log.i("YO", "used real loc");
count = 0;
}
else {
mockLoc.setLatitude(cityCoords.get(randIndex).latitude);
mockLoc.setLongitude(cityCoords.get(randIndex).longitude);
count++;
}
mockLoc.setAccuracy(20);
mockLoc.setTime(System.currentTimeMillis());
mockLoc.setElapsedRealtimeNanos(System.nanoTime());
Log.i("MockedLoc", mockLoc.toString());
try {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationServices.FusedLocationApi.setMockLocation(mGoogleApiClient, mockLoc);
if(!realm.isClosed()) {
String time = getDate(System.currentTimeMillis(), "dd/MM/yyyy hh:mm:ss.SSS");
realm.beginTransaction();
realm.where(Session.class).findFirst().getMobilityTrace()
.add(new com.djsg38.locationprivacyapp.models.Location()
.setLat(mockLoc.getLatitude())
.setLong(mockLoc.getLongitude())
.setTime(time));
realm.commitTransaction();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public static String getDate(long milliSeconds, String dateFormat)
{
// Create a DateFormatter object for displaying date in specified format.
SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
// Create a calendar object that will convert the date and time value in milliseconds to date.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milliSeconds);
return formatter.format(calendar.getTime());
}
// Begin faking the location
public void initiateMockLocs() {
setMockLocation();
updateMockLocation();
startTimer();
}
@Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Log.i("GoogleApiClient", "Connected");
initiateMockLocs();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(final Location location) {
Log.i("LocationChangedService", location.toString());
Session session = realm.where(Session.class).findFirst();
RealmList<com.djsg38.locationprivacyapp.models.Location>
mockLocs = session.getMockLocations();
if (mockLocs.where()
.equalTo("Lat", location.getLatitude())
.equalTo("Long", location.getLongitude()).findFirst() == null) {
realm.beginTransaction();
session.addNewMockLocation(location);
realm.commitTransaction();
}
}
// Initialize a GoogleApiClient object
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
// Initialize a LocationRequest object
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(10000);
mLocationRequest.setFastestInterval(10000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
}
}
I don't see any createObject()
or copyToRealm()
: how do you add objects in your Realm?
I add new objects to a RealmList which is a member of Trace
through the function trace.addNewSemanticTrace(temp);
, but does a RealmList.add(item)
. But as per the other thread, I guess I need to initialize that RealmList, as those are unmanaged objects. Below is the code that does:
public class Trace extends RealmObject {
public RealmList<Semantics> singleTrace;
private int ID;
public void setID(int id) {
this.ID = id;
}
public int getID() {
return ID;
}
public void addNewSemanticTrace(Semantics place) {
singleTrace.add(place);
}
public RealmList<Semantics> getSingleTrace() {
return singleTrace;
}
}
As per the other thread, I am closing this issue due to initialization of RealmList for unmanaged objects. I am so thankful for all of the help, especially to @zaki50 for helping me figure out I can have a RealmList of another Realm class which has a RealmList, to help fulfill my "List of Lists" idea.
I am having a problem correctly accessing the elements within a RealmList of mine. To begin, I will give some of my details necessary to understand the issue.
I have a base class:
Then an outer class:
Then another layer class:
In my code, I get a list of random locations (works correctly) and cycle through this list to find nearby place types, per Google Places API. Here is some code to show:
I know it's quite a bit, but I feel this is necessary to understand what I do. As you can see, for each location in which there are places found, I set an ID to the Trace and add each place to the trace. Then, at the end, I add that RealmList to another RealmList, as per another user told me I could do.
The problem forms when I try accessing this list later on with: `
My output is such:
It finds two traces, which I think is correct, since only two locations had places. However, the traces are the exact same with the same IDs. Instead, one trace should have
ID = 2
and one placeLandmark Plaza Frontenac
, which isn't even shown in these traces. Am I doing something wrong when adding the traces?Update: It seems that it keeps outputting the trace and ID of the LAST inserted ID and trace; it does not get the IDs nor traces of ALL the traces inserted. Not sure if I am just doing it wrong??