Sensor Scol plugin
Multi platform sensors for handled devices
SASensor.cpp
1
2# ifdef ANDROID
3
4#include <map>
5#include <vector>
6#include <android/sensor.h>
7#include <android_native_app_glue.h>
8#include <jni.h>
9#include "SSensor.h"
10#include "SASensor.h"
11#include "tools/SO3Util.h"
12#include <scolPlugin.h>
13
14
15/* * * * * * * * * * * * * DEVICE ORIENTATION * * * * * * * * * * * * */
16int getAndroidOrientation()
17{
18 int orient = 0;
19
20 struct android_app *androidApp = (struct android_app *) SCgetExtra("this_inst");
21 if (androidApp)
22 {
23 // get screen orientation from java
24 JNIEnv *env = 0;
25 ANativeActivity *nativeActivity = androidApp->activity;
26 nativeActivity->vm->AttachCurrentThread(&env, NULL);
27
28 /*
29 // Java code
30 mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
31 mDisplay = mWindowManager.getDefaultDisplay();
32 mRotation = mDisplay.getRotation();
33 */
34
35 jclass cContext = env->FindClass("android/content/Context");
36 jobject oContext = nativeActivity->clazz;
37
38 jfieldID fidWindowService = env->GetStaticFieldID(cContext, "WINDOW_SERVICE", "Ljava/lang/String;");
39 jstring sWindowService = (jstring) env->GetStaticObjectField(cContext, fidWindowService);
40
41 jclass cWinManager = env->FindClass("android/view/WindowManager");
42 jmethodID midgetsys = env->GetMethodID(cContext, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
43 jobject oWindowService = env->CallObjectMethod(oContext, midgetsys, sWindowService);
44
45 if (oWindowService)
46 {
47 jmethodID midGetDisplay = env->GetMethodID(cWinManager, "getDefaultDisplay", "()Landroid/view/Display;");
48 jclass cDisplay = env->FindClass("android/view/Display");
49 jobject oDisplay = env->CallObjectMethod(oWindowService, midGetDisplay);
50
51 if (oDisplay)
52 {
53 jmethodID midgetRot = env->GetMethodID(cDisplay, "getRotation", "()I");
54 orient = (int) env->CallIntMethod(oDisplay, midgetRot);
55 env->DeleteLocalRef(oDisplay);
56 }
57 env->DeleteLocalRef(cDisplay);
58 env->DeleteLocalRef(oWindowService);
59 }
60
61 env->DeleteLocalRef(cWinManager);
62 env->DeleteLocalRef(sWindowService);
63 env->DeleteLocalRef(cContext);
64
65 // release env
66 nativeActivity->vm->DetachCurrentThread();
67 }
68 return orient;
69}
70
71Vector3d getDeviceOrientationCorrection(DeviceOrientation orientation, Vector3d vec)
72{
73 Vector3d nvec = vec;
74 if (orientation == ROTATION_90)
75 {
76 nvec.x = vec.y;
77 nvec.y = vec.x;
78 nvec.z = vec.z;
79 }
80 else if (orientation == ROTATION_180)
81 {
82 nvec.x = -vec.x;
83 nvec.y = -vec.y;
84 nvec.z = vec.z;
85 }
86 else if (orientation == ROTATION_270)
87 {
88 nvec.x = -vec.y;
89 nvec.y = -vec.x;
90 nvec.z = vec.z;
91 }
92 return nvec;
93}
94
95/* * * * * * * * * * * * * EVENT CALLBACK * * * * * * * * * * * * */
96
97SSensorManager* SASensorManager::mSingletonInstance;
98
99
100/* * * * * * * * * * * * * SENSOR * * * * * * * * * * * * */
101
102SASensor::SASensor() : SSensor()
103{
104
105}
106
107SASensor::SASensor(SSensorType type) : SSensor(type)
108{
109
110}
111
112SASensor::~SASensor()
113{
114
115}
116
117SSensorData SASensor::GetData()
118{
119 return mData;
120}
121
122void SASensor::SetData(SSensorData newData)
123{
124 mData = newData;
125}
126
127ASensor* SASensor::GetASensor()
128{
129 return mASensor;
130}
131
132void SASensor::SetASensor(ASensor* aSensor)
133{
134 mASensor = aSensor;
135}
136
137Vector3d SASensor::GetLinearAcceleration(Vector3d acc)
138{
139 float alpha = 0.8f;
140
141 mGravity.x = alpha * mGravity.x + (1 - alpha) * acc.x;
142 mGravity.y = alpha * mGravity.y + (1 - alpha) * acc.y;
143 mGravity.z = alpha * mGravity.z + (1 - alpha) * acc.z;
144
145 return Vector3d(acc - mGravity);
146}
147
148 /* * * * * * * * * * * * * SENSOR MANAGER * * * * * * * * * * * * */
149
150SASensorManager::SASensorManager() : SSensorManager()
151{
152 mSensorList = std::set<SSensor*>();
153 mASensorManager = ASensorManager_getInstance();
154 mASensorEventQueue = 0;
155 mScreenOrientation = getAndroidOrientation();
156
157 ASensorList aSensorList;
158 // Get the list of available sensors
159 int nbSensor = ASensorManager_getSensorList(mASensorManager, &aSensorList);
160 MMechostr(MSKDEBUG, "SSensorManager() : %d sensors has been found", nbSensor);
161 for (int i = 0; i < nbSensor; i++)
162 {
163 const ASensor* aSensor = aSensorList[i];
164
165 // check if it's a default sensor
166 if (aSensor == ASensorManager_getDefaultSensor(mASensorManager,ASensor_getType(aSensor)))
167 {
168 switch (ASensor_getType(aSensor))
169 {
170 case ASENSOR_TYPE_ACCELEROMETER:
171 {
172 MMechostr(MSKDEBUG, "SSensorManager() : an accelerometer has been found (%d)", i);
173 SASensor* sensor = new SASensor(SSensorType::SSENSOR_TYPE_ACCELEROMETER);
174 sensor->SetASensor((ASensor*) aSensor);
175 mSensorList.insert(sensor);
176 break;
177 }
178 case ASENSOR_TYPE_MAGNETIC_FIELD:
179 {
180 MMechostr(MSKDEBUG, "SSensorManager() : a magnetometer has been found (%d)", i);
181 SASensor* sensor = new SASensor(SSensorType::SSENSOR_TYPE_MAGNETIC_FIELD);
182 sensor->SetASensor((ASensor*) aSensor);
183 mSensorList.insert(sensor);
184 break;
185 }
186 case ASENSOR_TYPE_GYROSCOPE:
187 {
188 MMechostr(MSKDEBUG, "SSensorManager() : a gyrometer has been found (%d)", i);
189 SASensor* sensor = new SASensor(SSensorType::SSENSOR_TYPE_GYROSCOPE);
190 sensor->SetASensor((ASensor*) aSensor);
191 mSensorList.insert(sensor);
192 break;
193 }
194 case ASENSOR_TYPE_LIGHT:
195 {
196 MMechostr(MSKDEBUG, "SSensorManager() : a light sensor has been found (%d)", i);
197 SASensor* sensor = new SASensor(SSensorType::SSENSOR_TYPE_LIGHT);
198 sensor->SetASensor((ASensor*) aSensor);
199 mSensorList.insert(sensor);
200 break;
201 }
202 case ASENSOR_TYPE_PROXIMITY:
203 {
204 MMechostr(MSKDEBUG, "SSensorManager() : a proximity sensor has been found (%d)", i);
205 SASensor* sensor = new SASensor(SSensorType::SSENSOR_TYPE_PROXIMITY);
206 sensor->SetASensor((ASensor*) aSensor);
207 mSensorList.insert(sensor);
208 break;
209 }
210
211 // >>>>> ADD HERE NEW SENSOR TYPES TO BE SUPPORTED <<<<<
212
213 default:
214 {
215 MMechostr(MSKDEBUG, "SSensorManager() : an unknown sensor has been found (%d)", i);
216 // mSensorMap[(ASensor*) aSensor] = new Sensor(SensorType::SSENSOR_TYPE_UNKNOWN);
217 break;
218 }
219 }
220 }
221 else
222 {
223 MMechostr(MSKDEBUG, "SSensorManager() : a secondary (non default) sensor has been found (%d)", i);
224 }
225 }
226
227 mTerminate = false;
228 mThread = boost::thread(boost::bind(&SASensorManager::UpdateThread, this));
229}
230
231DeviceOrientation SASensorManager::GetScreenOrientation()
232{
233 return (DeviceOrientation)mScreenOrientation;
234}
235
236void SASensorManager::UpdateThread()
237{
238 while (!mTerminate)
239 {
240 if (mASensorEventQueue == 0)
241 {
242 ALooper* looper = ALooper_forThread();
243 if (looper == 0)
244 looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
245
246 // Begin event monitoring
247 mASensorEventQueue = ASensorManager_createEventQueue(mASensorManager, looper, ALOOPER_POLL_CALLBACK, SASensorManager::UpdateSensorData, this);
248 }
249
250 int events;
251 struct android_poll_source* source;
252
253 ALooper_pollAll(0, NULL, &events, (void**)&source);
254
255 boost::this_thread::sleep_for(boost::chrono::milliseconds(5)); //DO not burn too much CPU
256 }
257
258 if (mASensorEventQueue)
259 {
260 ASensorManager_destroyEventQueue(mASensorManager, mASensorEventQueue);
261 mASensorEventQueue = 0;
262 }
263}
264
265int SASensorManager::UpdateSensorData(int fd, int events, void* data)
266{
267 boost::upgrade_lock< boost::shared_mutex > lock(mGlobalMutex);
268 SASensorManager* manager = (SASensorManager*)data;
269
270 ASensorEvent event;
271 while (ASensorEventQueue_getEvents(manager->GetASensorEventQueue(), &event, 1) > 0)
272 {
273 std::set<SSensor*> sensorList = manager->GetSensorList();
274 for (std::set<SSensor*>::iterator it = sensorList.begin(); it != sensorList.end(); ++it)
275 {
276 SASensor* csensor = (SASensor*)*it;
277 if (ASensor_getType(csensor->GetASensor()) == event.type)
278 {
279 if (csensor->IsEnabled())
280 {
281 SSensorData formatedData;
282 memset(&formatedData, 0, sizeof(formatedData));
283 formatedData.delta = csensor->GetElapsedTime(event.timestamp);
284
285 switch (event.type)
286 {
287 case ASENSOR_TYPE_ACCELEROMETER:
288 {
289 Vector3d vec(event.acceleration.x, event.acceleration.y, event.acceleration.z);
290 formatedData.vec3 = getDeviceOrientationCorrection((DeviceOrientation)manager->GetScreenOrientation(), vec);
291
292 csensor->CallSensorCb(formatedData);
293
294 if (manager->IsEnabled(SSENSOR_TYPE_ORIENTATION))
295 {
296 if (OrientationTracker* orientationTracker = manager->GetOrientationTracker())
297 {
298 vec *= ASENSOR_STANDARD_GRAVITY;
299 orientationTracker->processAcceleration(vec, event.timestamp);
300 }
301 }
302 break;
303 }
304 case ASENSOR_TYPE_GYROSCOPE:
305 {
306 Vector3d vec(event.vector.x, event.vector.y, event.vector.z);
307 formatedData.vec3 = getDeviceOrientationCorrection((DeviceOrientation)manager->GetScreenOrientation(), vec);
308
309 csensor->CallSensorCb(formatedData);
310
311 if (manager->IsEnabled(SSENSOR_TYPE_ORIENTATION))
312 {
313 if (OrientationTracker* orientationTracker = manager->GetOrientationTracker())
314 {
315 orientationTracker->processGyro(vec, event.timestamp);
316 }
317 }
318 break;
319 }
320 case ASENSOR_TYPE_MAGNETIC_FIELD:
321 {
322 formatedData.vec3.x = event.magnetic.x;
323 formatedData.vec3.y = event.magnetic.y;
324 formatedData.vec3.z = event.magnetic.z;
325
326 csensor->CallSensorCb(formatedData);
327
328 if (manager->IsEnabled(SSENSOR_TYPE_ORIENTATION) && manager->IsEnabled(SSENSOR_TYPE_MAGNETIC_FIELD))
329 {
330 if (OrientationTracker* orientationTracker = manager->GetOrientationTracker())
331 {
332 orientationTracker->processMag(formatedData.vec3, event.timestamp);
333 }
334 }
335 break;
336 }
337 case ASENSOR_TYPE_LIGHT:
338 {
339 formatedData.fval = event.light;
340
341 csensor->CallSensorCb(formatedData);
342
343 break;
344 }
345 case ASENSOR_TYPE_PROXIMITY:
346 {
347 formatedData.fval = event.distance;
348
349 csensor->CallSensorCb(formatedData);
350 break;
351 }
352
353 // >>>>> ADD HERE NEW SENSOR TYPES TO BE SUPPORTED <<<<<
354
355 default:
356 {
357 return 1; // TODO ERROR: INVALID SENSOR TYPE
358 }
359 }
360 csensor->SetData(formatedData);
361 }
362 }
363 }
364 }
365 return 1; // to continue to receive events in this callback
366}
367
368SASensorManager::~SASensorManager()
369{
370 mTerminate = true;
371 mThread.join();
372
373 for (std::set<SSensor*>::iterator it = mSensorList.begin(); it != mSensorList.end(); ++it)
374 {
375 SASensor* sensor = (SASensor*) (*it);
376 SAFE_DELETE(sensor);
377 }
378
379 mSingletonInstance = NULL;
380
381 JNIEnv* env = 0;
382 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
383 if (androidApp != NULL)
384 {
385 if (androidApp->activity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_EDETACHED)
386 androidApp->activity->vm->DetachCurrentThread();
387 }
388}
389
390ASensorEventQueue* SASensorManager::GetASensorEventQueue()
391{
392 return mASensorEventQueue;
393}
394
395int SASensorManager::SetSensorEnable(SSensorType sensorType, bool state)
396{
397 boost::shared_lock< boost::shared_mutex > lock(mGlobalMutex);
398
399 //wait for thread to start
400 while (mASensorEventQueue == 0)
401 boost::this_thread::sleep_for(boost::chrono::milliseconds(5));
402
403 // SOFTWARE SENSORS
404 if (sensorType == SSENSOR_TYPE_ORIENTATION && IsAvailable(SSENSOR_TYPE_ORIENTATION))
405 {
406 if (state)
407 {
408 GetOrientationTracker()->startTracking(GetScreenOrientation());
409 }
410 else
411 GetOrientationTracker()->stopTracking();
412
413 //let the scol dev define if he want to use the mag sensor
414 //SetSensorEnable(SSENSOR_TYPE_MAGNETIC_FIELD, state);
415 return SetSensorEnable(SSENSOR_TYPE_ACCELEROMETER, state) + SetSensorEnable(SSENSOR_TYPE_GYROSCOPE, state);
416 }
417 // PHYSICAL SENSORS
418 else
419 {
420 SSensor* sensor = GetSensorByType(sensorType);
421 if (sensor)
422 {
423 ASensor* aSensor = ((SASensor*) sensor)->GetASensor();
424 if (aSensor != NULL)
425 {
426 sensor->SetEnabled(state);
427 if (state)
428 {
429 ASensorEventQueue_enableSensor(mASensorEventQueue, aSensor);
430 ASensorEventQueue_setEventRate(mASensorEventQueue, aSensor, (1000L / 200) * 1000); // 200 Hz in microseconds
431 }
432 else
433 {
434 ASensorEventQueue_disableSensor(mASensorEventQueue, aSensor);
435 }
436 return 1;
437 }
438 else
439 {
440 // ERROR: NO ASENSOR FOUND
441 return -1;
442 }
443 }
444 else
445 {
446 // ERROR: NO SENSOR FOUND
447 return -2;
448 }
449 }
450}
451
452void SASensorManager::Vibrate(long millis)
453{
454 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
455 if (androidApp)
456 {
457 JNIEnv* env = 0;
458 ANativeActivity* nativeActivity = androidApp->activity;
459 if (nativeActivity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)
460 nativeActivity->vm->AttachCurrentThread(&env, NULL);
461
462 jobject oContext = nativeActivity->clazz;
463 jclass cContext = env->GetObjectClass(oContext);
464
465 jmethodID fidSystemService = env->GetMethodID(cContext, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
466 jstring svibrator = env->NewStringUTF("vibrator");
467 jobject oVibratorService = env->CallObjectMethod(oContext, fidSystemService, svibrator);
468
469 if (oVibratorService)
470 {
471 jclass cVibrator = env->GetObjectClass(oVibratorService);
472 jmethodID midHasVibrator = env->GetMethodID(cVibrator, "hasVibrator", "()Z");
473
474 int isavaible = 1;
475 if (env->ExceptionCheck())
476 {
477 // hasVibrator() doesn't exist on <= Android 2.3.4
478 env->ExceptionClear();
479 MMechostr(MSKRUNTIME, "Could not get hasVibrator method");
480 }
481 else
482 {
483 isavaible = (int)env->CallBooleanMethod(oVibratorService, midHasVibrator);
484 }
485
486 if (isavaible)
487 {
488 jmethodID midVibrate = env->GetMethodID(cVibrator, "vibrate", "(J)V");
489 env->CallVoidMethod(oVibratorService, midVibrate, (jlong)millis);
490 }
491 }
492 env->DeleteLocalRef(svibrator);
493 env->DeleteLocalRef(oVibratorService);
494 env->DeleteLocalRef(cContext);
495 }
496}
497
498void SASensorManager::StartVibration()
499{
500 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
501 if (androidApp)
502 {
503 JNIEnv* env = 0;
504 ANativeActivity* nativeActivity = androidApp->activity;
505 if (nativeActivity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)
506 nativeActivity->vm->AttachCurrentThread(&env, NULL);
507
508 jobject oContext = nativeActivity->clazz;
509 jclass cContext = env->GetObjectClass(oContext);
510
511 jmethodID fidSystemService = env->GetMethodID(cContext, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
512 jstring svibrator = env->NewStringUTF("vibrator");
513 jobject oVibratorService = env->CallObjectMethod(oContext, fidSystemService, svibrator);
514
515 if (oVibratorService)
516 {
517 jclass cVibrator = env->GetObjectClass(oVibratorService);
518 jmethodID midHasVibrator = env->GetMethodID(cVibrator, "hasVibrator", "()Z");
519
520 int isavaible = 1;
521 if (env->ExceptionCheck())
522 {
523 // hasVibrator() doesn't exist on <= Android 2.3.4
524 env->ExceptionClear();
525 MMechostr(MSKRUNTIME, "Could not get hasVibrator method");
526 }
527 else
528 {
529 isavaible = (int)env->CallBooleanMethod(oVibratorService, midHasVibrator);
530 }
531
532 if (isavaible)
533 {
534 jmethodID midVibrate = env->GetMethodID(cVibrator, "vibrate", "([JI)V");
535
536 jlongArray pattern = env->NewLongArray(2);
537 jlong t[2];
538 t[0] = 0;
539 t[1] = 10000;
540 env->SetLongArrayRegion(pattern, 0, 2, t);
541
542 // Get repeat index (-1 for no repeat by default)
543 env->CallVoidMethod(oVibratorService, midVibrate, pattern, 0);
544 env->DeleteLocalRef(pattern);
545 }
546 }
547 env->DeleteLocalRef(svibrator);
548 env->DeleteLocalRef(oVibratorService);
549 env->DeleteLocalRef(cContext);
550 }
551}
552
553void SASensorManager::VibratePattern(std::vector<int> pattern, bool loop)
554{
555 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
556 if (androidApp)
557 {
558 JNIEnv* env = 0;
559 ANativeActivity* nativeActivity = androidApp->activity;
560 if (nativeActivity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)
561 nativeActivity->vm->AttachCurrentThread(&env, NULL);
562
563 jobject oContext = nativeActivity->clazz;
564 jclass cContext = env->GetObjectClass(oContext);
565
566 jmethodID fidSystemService = env->GetMethodID(cContext, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
567 jstring svibrator = env->NewStringUTF("vibrator");
568 jobject oVibratorService = env->CallObjectMethod(oContext, fidSystemService, svibrator);
569
570 if (oVibratorService)
571 {
572 jclass cVibrator = env->GetObjectClass(oVibratorService);
573 jmethodID midHasVibrator = env->GetMethodID(cVibrator, "hasVibrator", "()Z");
574
575 int isavaible = 1;
576 if (env->ExceptionCheck())
577 {
578 // hasVibrator() doesn't exist on <= Android 2.3.4
579 env->ExceptionClear();
580 MMechostr(MSKRUNTIME, "Could not get hasVibrator method");
581 }
582 else
583 {
584 isavaible = (int)env->CallBooleanMethod(oVibratorService, midHasVibrator);
585 }
586
587 if (isavaible)
588 {
589 jmethodID midVibrate = env->GetMethodID(cVibrator, "vibrate", "([JI)V");
590
591 jlongArray jpattern = env->NewLongArray(pattern.size());
592 jlong t[pattern.size()];
593 for (unsigned int i = 0; i < pattern.size(); i++)
594 t[i] = (jlong)pattern[i];
595
596 env->SetLongArrayRegion(jpattern, 0, pattern.size(), t);
597
598 // Get repeat index (-1 for no repeat by default)
599 jint jloop = (loop == true) ? 0 : -1;
600 env->CallVoidMethod(oVibratorService, midVibrate, jpattern, jloop);
601 env->DeleteLocalRef(jpattern);
602 }
603 }
604 env->DeleteLocalRef(svibrator);
605 env->DeleteLocalRef(oVibratorService);
606 env->DeleteLocalRef(cContext);
607 }
608}
609
610
611void SASensorManager::StopVibration()
612{
613 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
614 if (androidApp)
615 {
616 JNIEnv* env = 0;
617 ANativeActivity* nativeActivity = androidApp->activity;
618 if (nativeActivity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)
619 nativeActivity->vm->AttachCurrentThread(&env, NULL);
620
621 jobject oContext = nativeActivity->clazz;
622 jclass cContext = env->GetObjectClass(oContext);
623
624 jmethodID fidSystemService = env->GetMethodID(cContext, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
625 jstring svibrator = env->NewStringUTF("vibrator");
626 jobject oVibratorService = env->CallObjectMethod(oContext, fidSystemService, svibrator);
627
628 if (oVibratorService)
629 {
630 jclass cVibrator = env->GetObjectClass(oVibratorService);
631 jmethodID midHasVibrator = env->GetMethodID(cVibrator, "hasVibrator", "()Z");
632
633 int isavaible = 1;
634 if (env->ExceptionCheck())
635 {
636 // hasVibrator() doesn't exist on <= Android 2.3.4
637 env->ExceptionClear();
638 MMechostr(MSKRUNTIME, "Could not get hasVibrator method");
639 }
640 else
641 {
642 isavaible = (int)env->CallBooleanMethod(oVibratorService, midHasVibrator);
643 }
644
645 if (isavaible)
646 {
647 jmethodID midVibrate = env->GetMethodID(cVibrator, "cancel", "()V");
648 env->CallVoidMethod(oVibratorService, midVibrate);
649 }
650 }
651 env->DeleteLocalRef(svibrator);
652 env->DeleteLocalRef(oVibratorService);
653 env->DeleteLocalRef(cContext);
654 }
655}
656
657
658void SASensorManager::StartLocationService()
659{
660 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
661 if (androidApp)
662 {
663 JNIEnv* env = 0;
664 ANativeActivity* nativeActivity = androidApp->activity;
665 if (nativeActivity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)
666 nativeActivity->vm->AttachCurrentThread(&env, NULL);
667
668 // Get class
669 jobject oActivity = nativeActivity->clazz;
670 jclass cActivity = env->GetObjectClass(oActivity);
671 if (cActivity)
672 {
673 jobject scolexternal_object = 0;
674 jclass scolexternal_clazz = 0;
675 jmethodID jStartLocationService = 0;
676
677 jfieldID scolexternal_fieldID = env->GetFieldID(cActivity, "mScolExternal", "Lorg/imaginer/scol/ScolExternal;");
678 if (scolexternal_fieldID)
679 scolexternal_object = env->GetObjectField(oActivity, scolexternal_fieldID);
680 if (scolexternal_object)
681 scolexternal_clazz = env->GetObjectClass(scolexternal_object);
682 if (scolexternal_clazz)
683 jStartLocationService = env->GetMethodID(scolexternal_clazz, "startLocationService", "()V");
684
685 if (env->ExceptionCheck())
686 env->ExceptionClear();
687
688 if (!jStartLocationService)
689 {
690 env->DeleteLocalRef(scolexternal_clazz);
691 env->DeleteLocalRef(scolexternal_object);
692 env->DeleteLocalRef(cActivity);
693 return;
694 }
695 env->CallVoidMethod(scolexternal_object, jStartLocationService);
696
697 // Release references
698 env->DeleteLocalRef(scolexternal_clazz);
699 env->DeleteLocalRef(scolexternal_object);
700
701 if (env->ExceptionCheck())
702 {
703 env->ExceptionClear();
704 MMechostr(MSKRUNTIME, "Android location exception : Check android.permission.FINE_LOCATION\n");
705 }
706
707 env->DeleteLocalRef(cActivity);
708 }
709 androidApp->activity->vm->DetachCurrentThread();
710 }
711}
712
713void SASensorManager::StopLocationService()
714{
715 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
716 if (androidApp)
717 {
718 JNIEnv* env = 0;
719 ANativeActivity* nativeActivity = androidApp->activity;
720 if (nativeActivity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)
721 nativeActivity->vm->AttachCurrentThread(&env, NULL);
722
723 // Get class
724 jobject oActivity = nativeActivity->clazz;
725 jclass cActivity = env->GetObjectClass(oActivity);
726 if (cActivity)
727 {
728 jobject scolexternal_object = 0;
729 jclass scolexternal_clazz = 0;
730 jmethodID jStopLocationService = 0;
731
732 jfieldID scolexternal_fieldID = env->GetFieldID(cActivity, "mScolExternal", "Lorg/imaginer/scol/ScolExternal;");
733 if (scolexternal_fieldID)
734 scolexternal_object = env->GetObjectField(oActivity, scolexternal_fieldID);
735 if (scolexternal_object)
736 scolexternal_clazz = env->GetObjectClass(scolexternal_object);
737 if (scolexternal_clazz)
738 jStopLocationService = env->GetMethodID(scolexternal_clazz, "stopLocationService", "()V");
739
740 if (env->ExceptionCheck())
741 env->ExceptionClear();
742
743 if (!jStopLocationService)
744 {
745 env->DeleteLocalRef(scolexternal_clazz);
746 env->DeleteLocalRef(scolexternal_object);
747 env->DeleteLocalRef(cActivity);
748 return;
749 }
750 env->CallVoidMethod(scolexternal_object, jStopLocationService);
751
752 if (env->ExceptionCheck())
753 {
754 env->ExceptionClear();
755 MMechostr(MSKRUNTIME, "Android location exception : Check android.permission.FINE_LOCATION\n");
756 }
757
758 // Release references
759 env->DeleteLocalRef(scolexternal_clazz);
760 env->DeleteLocalRef(scolexternal_object);
761 env->DeleteLocalRef(cActivity);
762 }
763 androidApp->activity->vm->DetachCurrentThread();
764 }
765}
766
767bool SASensorManager::GetLocation(float &longitude, float &latitude, float &altitude)
768{
769 longitude = 0.0f;
770 latitude = 0.0f;
771 altitude = 0.0f;
772
773 struct android_app* androidApp = (struct android_app*)SCgetExtra("this_inst");
774 if (androidApp)
775 {
776 JNIEnv* env = 0;
777 ANativeActivity* nativeActivity = androidApp->activity;
778 if (nativeActivity->vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK)
779 nativeActivity->vm->AttachCurrentThread(&env, NULL);
780
781 // Get class
782 jobject oActivity = nativeActivity->clazz;
783 jclass cActivity = env->GetObjectClass(oActivity);
784 if (cActivity)
785 {
786 jobject scolexternal_object = 0;
787 jclass scolexternal_clazz = 0;
788 jmethodID jGetLocationLongitude = 0;
789 jmethodID jGetLocationLatitude = 0;
790 jmethodID jGetLocationAltitude = 0;
791
792 jfieldID scolexternal_fieldID = env->GetFieldID(cActivity, "mScolExternal", "Lorg/imaginer/scol/ScolExternal;");
793 if (scolexternal_fieldID)
794 scolexternal_object = env->GetObjectField(oActivity, scolexternal_fieldID);
795 if (scolexternal_object)
796 scolexternal_clazz = env->GetObjectClass(scolexternal_object);
797 if (scolexternal_clazz)
798 jGetLocationLongitude = env->GetMethodID(scolexternal_clazz, "getLocationLongitude", "()F");
799
800 if (env->ExceptionCheck())
801 env->ExceptionClear();
802
803 if (!jGetLocationLongitude)
804 {
805 env->DeleteLocalRef(scolexternal_clazz);
806 env->DeleteLocalRef(scolexternal_object);
807 env->DeleteLocalRef(cActivity);
808 return false;
809 }
810 longitude = (float) env->CallFloatMethod(scolexternal_object, jGetLocationLongitude);
811
812 if (env->ExceptionCheck())
813 {
814 env->ExceptionClear();
815 MMechostr(MSKRUNTIME, "Android location exception : Check android.permission.FINE_LOCATION\n");
816
817 env->DeleteLocalRef(scolexternal_clazz);
818 env->DeleteLocalRef(scolexternal_object);
819 env->DeleteLocalRef(cActivity);
820 return false;
821 }
822
823 jGetLocationLatitude = env->GetMethodID(scolexternal_clazz, "getLocationLatitude", "()F");
824
825 if (env->ExceptionCheck())
826 env->ExceptionClear();
827
828 if (!jGetLocationLongitude)
829 {
830 env->DeleteLocalRef(scolexternal_clazz);
831 env->DeleteLocalRef(scolexternal_object);
832 env->DeleteLocalRef(cActivity);
833 return false;
834 }
835 latitude = (float)env->CallFloatMethod(scolexternal_object, jGetLocationLatitude);
836
837 if (env->ExceptionCheck())
838 {
839 env->ExceptionClear();
840 MMechostr(MSKRUNTIME, "Android location exception : Check android.permission.FINE_LOCATION\n");
841
842 env->DeleteLocalRef(scolexternal_clazz);
843 env->DeleteLocalRef(scolexternal_object);
844 env->DeleteLocalRef(cActivity);
845 return false;
846 }
847
848 jGetLocationAltitude = env->GetMethodID(scolexternal_clazz, "getLocationAltitude", "()F");
849
850 if (env->ExceptionCheck())
851 env->ExceptionClear();
852
853 if (!jGetLocationAltitude)
854 {
855 env->DeleteLocalRef(scolexternal_clazz);
856 env->DeleteLocalRef(scolexternal_object);
857 env->DeleteLocalRef(cActivity);
858 return false;
859 }
860 altitude = (float)env->CallFloatMethod(scolexternal_object, jGetLocationAltitude);
861
862 if (env->ExceptionCheck())
863 {
864 env->ExceptionClear();
865 MMechostr(MSKRUNTIME, "Android location exception : Check android.permission.FINE_LOCATION\n");
866
867 env->DeleteLocalRef(scolexternal_clazz);
868 env->DeleteLocalRef(scolexternal_object);
869 env->DeleteLocalRef(cActivity);
870 return false;
871 }
872
873 // Release references
874 env->DeleteLocalRef(scolexternal_clazz);
875 env->DeleteLocalRef(scolexternal_object);
876 env->DeleteLocalRef(cActivity);
877 return true;
878 }
879 }
880 return false;
881}
882
883#endif