Getting NMEA DATA in android - java
The current issue that I'm getting is that the OnNmeaListener is not returning the correct data from the NMEA using the GpsStatus.Listener therefore I tried the GNSS Status for the peace of mind, it ended up returning gibberish data , so I had to revert back to GpsStatus Listener. I also prior to using OnNmeaListener tried GpsStatus.NmeaListner and when used tried to add it to the GpsStatus Listener it would show up as an error and suggested that i typecast it to OnNmeaListener, when this is done and the app is built and all and then executed from the app, it would crash and then not work at all, and this is why i shifted to OnNmeaListener in the first place. Now to its credit the OnNmeaListener works just fine and doesn't crash at all, but the data it gives out is not at all accurate, I thought maybe this might have to be some sort of fault/error on the device side, I then proceeded to test it on two devices with different API levels of 25 and 28, On the the 25 Level device it just did not give half of the data whereas on the 28 level device the data is full but not accurate and correct.
This is the method that I'm currently using:
OnNmeaMessageListener nmeaMessageListener = new OnNmeaMessageListener () {
#Override
public void onNmeaMessage(String nmea , long timestamp) {
if (trackStarted == true && trackPaused == false) {
if (nmea.startsWith ( "$GPGGA" ) || nmea.startsWith ( "$GPRMC" )) {
//Log.d("TrackManagerService","NMEA:" + nmea);
try {
// out.write(nmea.getBytes());
if (continuesMode) {
dataOut.write ( nmea.getBytes () );
bufferedNMEALines++;
if (bufferedNMEALines >= 10) {
flushContinuesTrack ();
//dataOut.reset();
bufferedNMEALines = 0;
}
} else {
outCompressed.write ( nmea.getBytes () );
}
// Log.d("TrackManagerService","NMEA:" + nmea);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace ();
}
if (nmea.startsWith ( "$GPGGA" )) {
String[] nmeaSplit = nmea.split ( "," );
if (nmeaSplit.length > 10) {
if (nmeaSplit[9].length () > 0) {
try {
mslAltitude = Float.parseFloat ( nmeaSplit[9] );
} catch (NumberFormatException ex) {
mslAltitude = 0;
}
} else {
mslAltitude = 0.0f;
}
}
}
}
//if (markStarted && hasFix() && nmea.startsWith("$GPGGA")) {
if (markStarted && hasFix () && nmea.startsWith ( "$GPRMC" )) {
markProgress++;
trackListener.onMarkProgress ( markProgress );
if (markProgress >= markMax) {
stopMark ();
}
}
}
}
};
And this is the output it gives when called:
$Start,082719,260220;
$GPGGA,082721.42,2654.2979,N,08056.6065,E,0,100.000,0.000,M,M,0,*44
$GPRMC,082721.42,V,2654.2979,N,08056.6065,E,0.000,0.000,260220,E,N*01
$GPGGA,082722.41,2654.2979,N,08056.6065,E,0,100.000,0.000,M,M,0,*44
$GPRMC,082722.41,V,2654.2979,N,08056.6065,E,0.000,0.000,260220,E,N*01
$End,082802,260220;
$Start,082804,260220;
$GPGGA,082837.42,2654.2979,N,08056.6065,E,0,100.000,0.000,M,M,0,*4C
$GPRMC,082837.42,V,2654.2979,N,08056.6065,E,0.000,0.000,260220,E,N*09
$GPGGA,082838.42,2654.2979,N,08056.6065,E,0,100.000,0.000,M,M,0,*43
$GPGGA,082840.42,2654.2979,N,08056.6065,E,0,100.000,0.000,M,M,0,*4C
$End,082841,260220;
$Start,082921,260220;
$GPGGA,082923.40,2654.2982,N,08056.6059,E,0,100.000,0.000,M,M,0,*41
$GPRMC,082923.40,V,2654.2982,N,08056.6059,E,0.000,0.000,260220,E,N*04
$GPGGA,082924.40,2654.2982,N,08056.6059,E,0,100.000,0.000,M,M,0,*46
$GPRMC,082945.40,V,2654.2982,N,08056.6059,E,0.000,0.000,260220,E,N*04
$End,082945,260220;
And this is the output when called using GNSS listener:
$Start,080450,260220;������������������������������������������������������������������������������������������������������������������������������������������������������������������
Any Sort of way to make this works?
[EDIT]
This is the response from an iOS device, which was accepted by the sever:
$Start,150403,250220;
$GPGGA,150403.69,2654.29986954,N,8056.60312653,E,1,00,0.0,0.0,0,0.0,0,0.0,0000*42;
$GPRMC,150743.99,A,2654.29986954,N,8056.60260391,E,0.0,0.0,250220,0.0,E,A*5;
$GPRMC,150844.26,A,2654.29986954,N,8056.60260391,E,0.0,0.0,250220,0.0,E,A*9;
$GPRMC,150937.91,A,2654.30012894,N,8056.60312653,E,0.0,0.0,250220,0.0,E,A*e;
$GPGGA,150945.04,2654.30429840,N,8056.60781097,E,1,00,0.0,0.0,0,0.0,0000*42;
$GPRMC,150952.01,A,2654.29921722,N,8056.60364532,E,0.0,0.0,250220,0.0,E,A*2;
$End,150953,250220;
$GPGGA,150953.00,2654.29921722,N,8056.60364532,E,1,00,0.0,0.0,0,0.0,0000*42;
$GPRMC,150953.00,A,2654.29921722,N,8056.60364532,E,0.0,0.0,250220,0.0,E,A*2;
Now, I DO NOT have the faintest idea how this works on an iOS device,(a Senior of mine worked on that and gave me this data) but somehow it worked on that and when the same logic was implemented on Android and the data was uploaded to the server it wouldn't accept it, whereas when the iOS data was manipulated in any sort of way ( removing lines, addlines, removing semi-colons, commas,etc.) it would somehow still work.
Related
How to get IMSI in Android 10 (Android Q)
I'm unable to get IMSI in Android 10. The Code that I was using to fetch IMSI number is giving an exception. java.lang.SecurityException: getSubscriberId: The user 10099 does not meet the requirements to access device identifiers. I understand that from android 10, google has restricted this information and its not accessible to third party apps due to privacy concerns but I'm looking for a workaround. The code that I was using is: private void getImsiNumber() { Utility.DEBUG_LOG(TAG,"+ getImsiNumber +"); if ( this.imsiNumber == null ) { Utility.DEBUG_LOG(TAG,"step 1"); TelephonyManager telephonyManager = (TelephonyManager) DashboardContainer.this.getSystemService(Context.TELEPHONY_SERVICE); Utility.DEBUG_LOG(TAG,"step 2"); try { this.imsiNumber = telephonyManager.getSubscriberId(); Utility.DEBUG_LOG(TAG,"step 3"); if ( this.imsiNumber == null || this.imsiNumber.length() == 0 ) { Utility.DEBUG_LOG(TAG,"imsiNumber:"+this.imsiNumber); this.imsiNumber = "WiFi"; } } catch (Exception e ) { Utility.DEBUG_LOG(TAG,"Exception:"+e.getMessage().toString()); } Utility.DEBUG_LOG(TAG,"IMSI Number:"+this.imsiNumber); SharedPref.write("imsiNumber",this.imsiNumber); Constants.IMSI_NO = this.imsiNumber; } }
How to implement ZenPolicy rules?
Does anyone here know anything about ZenPolicy and how to implement a rule? I am trying to replicate the Do Not Disturb setting where calls are not allowed through, but exceptions are possible, eg. Media sounds, Touch sounds etc. I have managed to disallow calls but when I toggle the exceptions settings (from my app), this reverts to "starred contacts only". I am attaching a screenshot of what I am trying to replicate in my app. Here is the code I am using so far: 3 -> { notificationManager.setInterruptionFilter( NotificationManager.INTERRUPTION_FILTER_PRIORITY ) notificationManager.setNotificationPolicy( NotificationManager.Policy( PEOPLE_TYPE_NONE, PRIORITY_SENDERS_ANY, PRIORITY_SENDERS_ANY ) ) } I have also looked through: https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/service/notification/ZenModeConfig.java;drc=master;l=754 and https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/service/notification/ZenPolicy.java and came up with this function, but it doesn't do anything...: fun zenPolicyBuilder(): ZenPolicy.Builder { val builder = ZenPolicy.Builder() val calls = PRIORITY_CATEGORY_CALLS val repeatCallers = PRIORITY_CATEGORY_REPEAT_CALLERS val alarms = PRIORITY_CATEGORY_ALARMS val media = PRIORITY_CATEGORY_MEDIA val system = PRIORITY_CATEGORY_SYSTEM val events = PRIORITY_CATEGORY_EVENTS val reminders = PRIORITY_CATEGORY_REMINDERS return when { calls != ZenPolicy.PEOPLE_TYPE_UNSET -> { builder.allowCalls(PEOPLE_TYPE_NONE) } repeatCallers != ZenPolicy.STATE_UNSET -> { builder.allowRepeatCallers(repeatCallers == ZenPolicy.STATE_ALLOW) } alarms != ZenPolicy.STATE_UNSET -> { builder.allowAlarms(alarms == ZenPolicy.STATE_ALLOW) } media != ZenPolicy.STATE_UNSET -> { builder.allowMedia(media == ZenPolicy.STATE_ALLOW) } system != ZenPolicy.STATE_UNSET -> { builder.allowSystem(system == ZenPolicy.STATE_ALLOW) } events != ZenPolicy.STATE_UNSET -> { builder.allowEvents(events == ZenPolicy.STATE_ALLOW) } reminders != ZenPolicy.STATE_UNSET -> { builder.allowReminders(reminders == ZenPolicy.STATE_ALLOW) } else -> builder } }
For anyone who might be interested in future, the first code snippet that I posted actually works fine. The problem was coming from another part of my code which was interfering with this.
Finding which item(s) in a list is not present in the Realm
I am using the latest Java Realm local database backing a mobile app. I have a Profile class and a Contact class in the app. Each Profile object can be associated with one or more Contact objects. Upon startup, I want to reconcile against a similar Profile/Contact list on my website to insure that the mobile app is using the latest/greatest definition of the Profile/Contact relationship. After validating the Profile during login, I then query the website to get the list of Contact email addresses associated with the Profile. I now need to do the following: For each Contact email address in the list from the website, make sure that the local Realm Contact object shows as "connected" to the Profile object. For each Contact object NOT in the list from the website, make sure that the local Realm Contact object shows as "not connected" to the Profile object. So what I'm doing is after login, executing an AsyncTask that: try { realm.beginTransaction(); RealmResults<Contact> contactResults; contactResults = realm.where(Contact.class).findAll(); if ( contactResults.size() == 0 ) { // Nothing to do return false; } // First set everything as not connected, then set only those passed in as connected contactResults.setBoolean(IS_CONNECTED, false); // Now update just the email addresses passed in as connected contactResults = realm.where(Contact.class).in(EMAIL_ADDRESS, emailList.toArray(new String[0])).findAll(); if ( contactResults.size() > 0) { contactResults.setBoolean(IS_CONNECTED, true); } //TODO - what if an item passed in is not yet in Contact list? success = true; } catch (Exception e) { Timber.d("Exception resetting contacts status: %s", e.getMessage()); } finally { if (success) { realm.commitTransaction(); } else { realm.cancelTransaction(); } } How I've done the first two pieces of work seem ok to me - as this app won't be scaling to thousands of "friends", resetting the contact to FALSE for everyone then to TRUE for the current set retrieved from the website is doable. However, the third piece has me stumped - is there a single call I can make to identify which, if any, of the email addresses in the passed array aren't actually in my Contact object RealmResults and therefore need to be added as new objects? Seems inefficient to loop through that list and check each one, one at a time, particularly since I've already performed two queries. The only solution I've come up with so far is this: try { realm.beginTransaction(); fullContactResults = realm.where(Contact.class).findAll(); if ( fullContactResults.size() > 0 ) { // First set everything as not connected, then set only those passed in as connected fullContactResults.setBoolean(IS_CONNECTED, false); } // Now for each item in the list we were passed in find it and update it, or add it. for ( String data : contactData ) { Contact c = null; String[] contactStruct = data.split(BODY_COMPONENTS_SEPARATOR); RealmResults<Contact> partialContactResults = realm.where(Contact.class) .equalTo(EMAIL_ADDRESS, contactStruct[CONNECTION_EMAIL_ELE]) .findAll(); if (partialContactResults.size() > 0 ) { c = partialContactResults.first(); } else { // Need to add the contact c = realm.createObject(Contact.class, UUID.randomUUID().toString()); } c.setConnected(true); c.setDisplayName(contactStruct[CONNECTION_FIRSTNAME_ELE] + " " + contactStruct[CONNECTION_LASTNAME_ELE]); c.setEmailAddress(contactStruct[CONNECTION_EMAIL_ELE]); } success = true; } catch (Exception e) { Timber.d("Exception resetting contacts status: %s", e.getMessage()); } finally { if (success) { realm.commitTransaction(); } else { realm.cancelTransaction(); } } Which does a loop and either updates or inserts. Any better way?
Why i get result.get(CaptureResult.CONTROL_AF_STATE); == INACTIVE?
I work with camera2API on Samsung S5 and if i try get state of focus i get value 0 which is equals to CaptureResult.CONTROL_AF_STATE_INACTIVE... There is snip of code : private void process(CaptureResult result) { switch (mState) { case CameraHelper.STATE_PREVIEW: { // We have nothing to do when the camera preview is working normally. here i get ---> Integer afState = result.get(CaptureResult.CONTROL_AF_STATE); if (CaptureResult.CONTROL_AF_TRIGGER_START == afState) { if (areWeFocused) { Log.e("---!!! HERE !!!--- :", String.valueOf(areWeFocused)); }else { } } if (CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState) { areWeFocused = true; } else { areWeFocused = false; } break; } But i also tried to test it on my Meizu MX5 and i get 1 - CaptureResult.CONTROL_AF_TRIGGER_START or 2 - CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED Question is : what is the difference in my code? Why do i get 0 in one case and 1 or 2 in another?
I know this is an old question, but i just ran into the same issue. Read through the Android docs about ControlAfState (AF = Auto Focus for those who are unaware, like I was). If AutoFocus Mode (afMode) is set to AF_MODE_OFF you will get the ControlAfState of Inactive. Android CaptureResult.CONTROL_AF_STATE
Prevent continuous F5 on a web application
This is related with handling the scenario when some crazy user is holding down the F5 key to send unlimited requests to our server. Our application is very much database and cache intensive and when such consecutive requests come in; our web application is crashing after some time. I know we need to fix the application cache handling and need to add some check at the web server but I am asked to take care of this issue in our code. I am handling this on both Javascript and server side, but looks like still it is failing, so would like to know if you have any better solution. My code is as follows: Javascript Code: function checkPageRefresh(e) { e = e || window.event; ar isPageRefreshed = false; // detect if user tries to refresh if ((e.keyCode == 116) /* F5 */ || (e.ctrlKey && (e.keyCode == 116)) /* Ctrl-F5 */ || (e.ctrlKey && (e.keyCode == 82)) /* Ctrl-R */) { isPageRefreshed = true; } // only trigger special handling for page refresh if (isPageRefreshed){ var lastRefreshTimeMillis= readCookie("last_refresh"); var currentTimeMillis = new Date().getTime(); // set cookie with now as last refresh time createCookie(lastRefreshCookieName, currentTimeMillis); var lastRefreshParsed = parseFloat(lastRefreshTimeMillis, 10); var timeDiff = currentTimeMillis - lastRefreshParsed; var F5RefreshTimeLimitMillis = <%=request.getAttribute("F5RefreshTimeLimitMillis")%>; // if detected last refresh was within 1 second, abort refresh if (timeDiff < F5RefreshTimeLimitMillis) { if (e.preventDefault) { e.preventDefault(); return; } } } // end if (isPageRefreshed) } Java Code: Queue<VisitsInfoHolder> recentlyVisitedUrls = (LinkedList<VisitsInfoHolder>)session.getAttribute(SupportWebKeys.RECENTLY_VISITED_URLS); String urlBeingCalled = PageUrlUtils.getFullURL(request); int maxCountOfRecentURLs = 3; if(null != recentlyVisitedUrls){ //verify if last visit count is matching with the count provided if(recentlyVisitedUrls.size() >= maxCountOfRecentURLs ) { int noOfMatchingVisits = 0; Long firstAccessedTime = 0l; int count = 0; for(VisitsInfoHolder urlIno : recentlyVisitedUrls) { //Store the time stamp of the first record if(count == 0 && null != urlIno) { firstAccessedTime = urlIno.getTimeOfTheVisit(); } count++; //count how many visits to the current page if(null != urlIno && null != urlIno.getUrl() && urlIno.getUrl().equalsIgnoreCase(urlBeingCalled)) { noOfMatchingVisits++; } } if (noOfMatchingVisits >= maxCountOfRecentURLs && (new Date().getTime() - firstAccessedTime) <= 1000){ LOGGER.error(">>>>> Redirecting the client to the warning page."); VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime()); recentlyVisitedUrls.remove(); recentlyVisitedUrls.add(currentVisitInfo); response.sendRedirect((String)request.getAttribute("F5IssueRedirectPage")); LOGGER.error(">>>>> Redirected successfully."); return; } else{ VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime()); recentlyVisitedUrls.remove(); recentlyVisitedUrls.add(currentVisitInfo); session.setAttribute(SupportWebKeys.RECENTLY_VISITED_URLS, recentlyVisitedUrls); } } else if (recentlyVisitedUrls.size() < maxCountOfRecentURLs) { VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime()); recentlyVisitedUrls.add(currentVisitInfo); session.setAttribute(SupportWebKeys.RECENTLY_VISITED_URLS, recentlyVisitedUrls); } } else{ recentlyVisitedUrls = new LinkedList<VisitsInfoHolder>(); VisitsInfoHolder currentVisitInfo = new VisitsInfoHolder(urlBeingCalled,new Date().getTime()); recentlyVisitedUrls.add(currentVisitInfo); session.setAttribute(SupportWebKeys.RECENTLY_VISITED_URLS, recentlyVisitedUrls); } Now I keep holding the F5 button then my Javascript is not understanding that the same key is held for longer time and server side code prints the following 2 loggers Redirecting the client to the warning page. Redirected successfully. But in reality it is not redirecting any single time. I tried adding Thread.sleep(1000) before and after redirect, but still no luck. Please let me know if you see any issue with my code or let me know if there is any better solution.
When you reproduce this problem are you the only person on your server? Can you reproduce this problem on your local dev instance? If so you really need to fix your server code such that it doesn't crash. You are doing something on your server that is too intensive and needs to be optimized. Simply intercepting the F5 key on someone's browser is treating the symptoms not the disease. If you are having problems handling a single user hitting F5 really quickly it simply means you'll never be able to scale up to many simultaneous users because that's the exact same request/response pattern as a single user round tripping you with F5. It's time to break out the profiler and check the timings on how long it takes to process a single request through the system. Then look for hotspots and optimize it. Also watch your memory usage see if you are cleaning things up or if they are growing off into infinity.