Mohammed Khider
8 years ago
38 changed files with 2486 additions and 4 deletions
@ -0,0 +1,9 @@ |
|||||||
|
*.iml |
||||||
|
.gradle |
||||||
|
/local.properties |
||||||
|
/.idea/workspace.xml |
||||||
|
/.idea/libraries |
||||||
|
.DS_Store |
||||||
|
/build |
||||||
|
/captures |
||||||
|
.externalNativeBuild |
@ -0,0 +1,19 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<module external.linked.project.id="GNSSLogger" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4"> |
||||||
|
<component name="FacetManager"> |
||||||
|
<facet type="java-gradle" name="Java-Gradle"> |
||||||
|
<configuration> |
||||||
|
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" /> |
||||||
|
<option name="BUILDABLE" value="false" /> |
||||||
|
</configuration> |
||||||
|
</facet> |
||||||
|
</component> |
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true"> |
||||||
|
<exclude-output /> |
||||||
|
<content url="file://$MODULE_DIR$"> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.gradle" /> |
||||||
|
</content> |
||||||
|
<orderEntry type="inheritedJdk" /> |
||||||
|
<orderEntry type="sourceFolder" forTests="false" /> |
||||||
|
</component> |
||||||
|
</module> |
@ -0,0 +1,148 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4"> |
||||||
|
<component name="FacetManager"> |
||||||
|
<facet type="android-gradle" name="Android-Gradle"> |
||||||
|
<configuration> |
||||||
|
<option name="GRADLE_PROJECT_PATH" value=":app" /> |
||||||
|
</configuration> |
||||||
|
</facet> |
||||||
|
<facet type="android" name="Android"> |
||||||
|
<configuration> |
||||||
|
<option name="SELECTED_BUILD_VARIANT" value="debug" /> |
||||||
|
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" /> |
||||||
|
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" /> |
||||||
|
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" /> |
||||||
|
<afterSyncTasks> |
||||||
|
<task>generateDebugSources</task> |
||||||
|
</afterSyncTasks> |
||||||
|
<option name="ALLOW_USER_CONFIGURATION" value="false" /> |
||||||
|
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" /> |
||||||
|
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" /> |
||||||
|
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" /> |
||||||
|
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" /> |
||||||
|
</configuration> |
||||||
|
</facet> |
||||||
|
</component> |
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false"> |
||||||
|
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" /> |
||||||
|
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" /> |
||||||
|
<exclude-output /> |
||||||
|
<content url="file://$MODULE_DIR$"> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" /> |
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support.test.espresso/espresso-core/2.2.2/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support.test.espresso/espresso-idling-resource/2.2.2/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support.test/exposed-instrumentation-api-publish/0.5/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support.test/rules/0.5/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support.test/runner/0.5/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/animated-vector-drawable/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-compat/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-core-ui/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-core-utils/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-fragment/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-media-compat/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v13/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-vector-drawable/24.2.1/jars" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> |
||||||
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" /> |
||||||
|
</content> |
||||||
|
<orderEntry type="jdk" jdkName="Android API 24 Platform" jdkType="Android SDK" /> |
||||||
|
<orderEntry type="sourceFolder" forTests="false" /> |
||||||
|
<orderEntry type="library" exported="" name="support-v4-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-compat-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="animated-vector-drawable-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-fragment-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="runner-0.5" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="espresso-idling-resource-2.2.2" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-library-1.3" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-integration-1.3" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="jsr305-2.0.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="design-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-media-compat-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-v13-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="espresso-core-2.2.2" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="exposed-instrumentation-api-publish-0.5" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-core-ui-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="recyclerview-v7-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="rules-0.5" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="appcompat-v7-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-vector-drawable-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="javax.annotation-api-1.2" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-core-utils-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="javax.inject-1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" name="support-annotations-24.2.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="javawriter-2.1.1" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-core-1.3" level="project" /> |
||||||
|
<orderEntry type="library" exported="" scope="TEST" name="junit-4.12" level="project" /> |
||||||
|
</component> |
||||||
|
</module> |
@ -0,0 +1,31 @@ |
|||||||
|
apply plugin: 'com.android.application' |
||||||
|
|
||||||
|
android { |
||||||
|
compileSdkVersion 24 |
||||||
|
buildToolsVersion "23.0.1" |
||||||
|
defaultConfig { |
||||||
|
applicationId "com.google.android.apps.location.gps.gnsslogger" |
||||||
|
minSdkVersion 24 |
||||||
|
targetSdkVersion 24 |
||||||
|
versionCode 1 |
||||||
|
versionName "1.0" |
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" |
||||||
|
} |
||||||
|
buildTypes { |
||||||
|
release { |
||||||
|
minifyEnabled false |
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
compile fileTree(include: ['*.jar'], dir: 'libs') |
||||||
|
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { |
||||||
|
exclude group: 'com.android.support', module: 'support-annotations' |
||||||
|
}) |
||||||
|
compile 'com.android.support:appcompat-v7:24.2.1' |
||||||
|
testCompile 'junit:junit:4.12' |
||||||
|
compile 'com.android.support:design:24.2.1' |
||||||
|
compile 'com.android.support:support-v13:24.2.1' |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
# Add project specific ProGuard rules here. |
||||||
|
# By default, the flags in this file are appended to flags specified |
||||||
|
# in /media/build/master/prebuilts/fullsdk/linux/tools/proguard/proguard-android.txt |
||||||
|
# You can edit the include path and order by changing the proguardFiles |
||||||
|
# directive in build.gradle. |
||||||
|
# |
||||||
|
# For more details, see |
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html |
||||||
|
|
||||||
|
# Add any project specific keep options here: |
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following |
||||||
|
# and specify the fully qualified class name to the JavaScript interface |
||||||
|
# class: |
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { |
||||||
|
# public *; |
||||||
|
#} |
@ -0,0 +1,23 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
package="com.google.android.apps.location.gps.gnsslogger" > |
||||||
|
|
||||||
|
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="24" /> |
||||||
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> |
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
||||||
|
<application |
||||||
|
android:allowBackup="true" |
||||||
|
android:icon="@drawable/ic_launcher" |
||||||
|
android:label="@string/app_name" |
||||||
|
android:theme="@style/AppTheme" > |
||||||
|
<activity |
||||||
|
android:name="com.google.android.apps.location.gps.gnsslogger.MainActivity" |
||||||
|
android:screenOrientation="portrait" |
||||||
|
android:label="@string/app_name" > |
||||||
|
<intent-filter> |
||||||
|
<action android:name="android.intent.action.MAIN" /> |
||||||
|
<category android:name="android.intent.category.LAUNCHER" /> |
||||||
|
</intent-filter> |
||||||
|
</activity> |
||||||
|
</application> |
||||||
|
</manifest> |
@ -0,0 +1,401 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.content.Intent; |
||||||
|
import android.location.GnssClock; |
||||||
|
import android.location.GnssMeasurement; |
||||||
|
import android.location.GnssMeasurementsEvent; |
||||||
|
import android.location.GnssNavigationMessage; |
||||||
|
import android.location.GnssStatus; |
||||||
|
import android.location.Location; |
||||||
|
import android.location.LocationManager; |
||||||
|
import android.net.Uri; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.os.Environment; |
||||||
|
import android.os.SystemClock; |
||||||
|
import android.util.Log; |
||||||
|
import android.widget.Toast; |
||||||
|
import com.google.android.apps.location.gps.gnsslogger.LoggerFragment.UIFragmentComponent; |
||||||
|
import java.io.BufferedWriter; |
||||||
|
import java.io.File; |
||||||
|
import java.io.FileFilter; |
||||||
|
import java.io.FileWriter; |
||||||
|
import java.io.IOException; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Locale; |
||||||
|
|
||||||
|
/** |
||||||
|
* A GNSS logger to store information to a file. |
||||||
|
*/ |
||||||
|
public class FileLogger implements GnssListener { |
||||||
|
|
||||||
|
private static final String TAG = "FileLogger"; |
||||||
|
private static final String FILE_PREFIX = "pseudoranges"; |
||||||
|
private static final String ERROR_WRITING_FILE = "Problem writing to file."; |
||||||
|
private static final String COMMENT_START = "# "; |
||||||
|
private static final char RECORD_DELIMITER = ','; |
||||||
|
private static final String VERSION_TAG = "Version: "; |
||||||
|
private static final String FILE_VERSION = "1.4.0.0, Platform: N"; |
||||||
|
|
||||||
|
private static final int MAX_FILES_STORED = 100; |
||||||
|
private static final int MINIMUM_USABLE_FILE_SIZE_BYTES = 1000; |
||||||
|
|
||||||
|
private final Context mContext; |
||||||
|
|
||||||
|
private final Object mFileLock = new Object(); |
||||||
|
private BufferedWriter mFileWriter; |
||||||
|
private File mFile; |
||||||
|
|
||||||
|
private UIFragmentComponent mUiComponent; |
||||||
|
|
||||||
|
public synchronized UIFragmentComponent getUiComponent() { |
||||||
|
return mUiComponent; |
||||||
|
} |
||||||
|
|
||||||
|
public synchronized void setUiComponent(UIFragmentComponent value) { |
||||||
|
mUiComponent = value; |
||||||
|
} |
||||||
|
|
||||||
|
public FileLogger(Context context) { |
||||||
|
this.mContext = context; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Start a new file logging process. |
||||||
|
*/ |
||||||
|
public void startNewLog() { |
||||||
|
synchronized (mFileLock) { |
||||||
|
File baseDirectory; |
||||||
|
String state = Environment.getExternalStorageState(); |
||||||
|
if (Environment.MEDIA_MOUNTED.equals(state)) { |
||||||
|
baseDirectory = new File(Environment.getExternalStorageDirectory(), FILE_PREFIX); |
||||||
|
baseDirectory.mkdirs(); |
||||||
|
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { |
||||||
|
logError("Cannot write to external storage."); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
logError("Cannot read external storage."); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat("yyy_MM_dd_HH_mm_ss"); |
||||||
|
Date now = new Date(); |
||||||
|
String fileName = String.format("%s_log_%s.txt", FILE_PREFIX, formatter.format(now)); |
||||||
|
File currentFile = new File(baseDirectory, fileName); |
||||||
|
String currentFilePath = currentFile.getAbsolutePath(); |
||||||
|
BufferedWriter currentFileWriter; |
||||||
|
try { |
||||||
|
currentFileWriter = new BufferedWriter(new FileWriter(currentFile)); |
||||||
|
} catch (IOException e) { |
||||||
|
logException("Could not open file: " + currentFilePath, e); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// initialize the contents of the file
|
||||||
|
try { |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.write("Header Description:"); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.write(VERSION_TAG); |
||||||
|
currentFileWriter.write(FILE_VERSION); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.write( |
||||||
|
"Raw,ElapsedRealtimeMillis,TimeNanos,LeapSecond,TimeUncertaintyNanos,FullBiasNanos," |
||||||
|
+ "BiasNanos,BiasUncertaintyNanos,DriftNanosPerSecond,DriftUncertaintyNanosPerSecond," |
||||||
|
+ "HardwareClockDiscontinuityCount, Svid,TimeOffsetNanos,State,ReceivedSvTimeNanos," |
||||||
|
+ "ReceivedSvTimeUncertaintyNanos,Cn0DbHz,PseudorangeRateMetersPerSecond," |
||||||
|
+ "PseudorangeRateUncertaintyMetersPerSecond," |
||||||
|
+ "AccumulatedDeltaRangeState,AccumulatedDeltaRangeMeters," |
||||||
|
+ "AccumulatedDeltaRangeUncertaintyMeters,CarrierFrequencyHz,CarrierCycles," |
||||||
|
+ "CarrierPhase,CarrierPhaseUncertainty,MultipathIndicator,SnrInDb," |
||||||
|
+ "ConstellationType"); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.write( |
||||||
|
"Fix,Provider,Latitude,Longitude,Altitude,Speed,Accuracy,(UTC)TimeInMs"); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.write("Nav,Svid,Type,Status,MessageId,Sub-messageId,Data(Bytes)"); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
currentFileWriter.write(COMMENT_START); |
||||||
|
currentFileWriter.newLine(); |
||||||
|
} catch (IOException e) { |
||||||
|
logException("Count not initialize file: " + currentFilePath, e); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (mFileWriter != null) { |
||||||
|
try { |
||||||
|
mFileWriter.close(); |
||||||
|
} catch (IOException e) { |
||||||
|
logException("Unable to close all file streams.", e); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
mFile = currentFile; |
||||||
|
mFileWriter = currentFileWriter; |
||||||
|
Toast.makeText(mContext, "File opened: " + currentFilePath, Toast.LENGTH_SHORT).show(); |
||||||
|
|
||||||
|
// To make sure that files do not fill up the external storage:
|
||||||
|
// - Remove all empty files
|
||||||
|
FileFilter filter = new FileToDeleteFilter(mFile); |
||||||
|
for (File existingFile : baseDirectory.listFiles(filter)) { |
||||||
|
existingFile.delete(); |
||||||
|
} |
||||||
|
// - Trim the number of files with data
|
||||||
|
File[] existingFiles = baseDirectory.listFiles(); |
||||||
|
int filesToDeleteCount = existingFiles.length - MAX_FILES_STORED; |
||||||
|
if (filesToDeleteCount > 0) { |
||||||
|
Arrays.sort(existingFiles); |
||||||
|
for (int i = 0; i < filesToDeleteCount; ++i) { |
||||||
|
existingFiles[i].delete(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Send the current log via email or other options selected from a pop menu shown to the user. A |
||||||
|
* new log is started when calling this function. |
||||||
|
*/ |
||||||
|
public void send() { |
||||||
|
if (mFile == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
Intent emailIntent = new Intent(Intent.ACTION_SEND); |
||||||
|
emailIntent.setType("*/*"); |
||||||
|
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "SensorLog"); |
||||||
|
emailIntent.putExtra(Intent.EXTRA_TEXT, ""); |
||||||
|
// attach the file
|
||||||
|
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(mFile)); |
||||||
|
getUiComponent().startActivity(Intent.createChooser(emailIntent, "Send log..")); |
||||||
|
if (mFileWriter != null) { |
||||||
|
try { |
||||||
|
mFileWriter.close(); |
||||||
|
mFileWriter = null; |
||||||
|
} catch (IOException e) { |
||||||
|
logException("Unable to close all file streams.", e); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onProviderEnabled(String provider) {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onProviderDisabled(String provider) {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onLocationChanged(Location location) { |
||||||
|
if (location.getProvider().equals(LocationManager.GPS_PROVIDER)) { |
||||||
|
synchronized (mFileLock) { |
||||||
|
if (mFileWriter == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
String locationStream = |
||||||
|
String.format( |
||||||
|
Locale.US, |
||||||
|
"Fix,%s,%f,%f,%f,%f,%f,%d", |
||||||
|
location.getProvider(), |
||||||
|
location.getLatitude(), |
||||||
|
location.getLongitude(), |
||||||
|
location.getAltitude(), |
||||||
|
location.getSpeed(), |
||||||
|
location.getAccuracy(), |
||||||
|
location.getTime()); |
||||||
|
try { |
||||||
|
mFileWriter.write(locationStream); |
||||||
|
mFileWriter.newLine(); |
||||||
|
} catch (IOException e) { |
||||||
|
logException(ERROR_WRITING_FILE, e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onLocationStatusChanged(String provider, int status, Bundle extras) {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssMeasurementsReceived(GnssMeasurementsEvent event) { |
||||||
|
synchronized (mFileLock) { |
||||||
|
if (mFileWriter == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
GnssClock gnssClock = event.getClock(); |
||||||
|
for (GnssMeasurement measurement : event.getMeasurements()) { |
||||||
|
try { |
||||||
|
writeGnssMeasurementToFile(gnssClock, measurement); |
||||||
|
} catch (IOException e) { |
||||||
|
logException(ERROR_WRITING_FILE, e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssMeasurementsStatusChanged(int status) {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssNavigationMessageReceived(GnssNavigationMessage navigationMessage) { |
||||||
|
synchronized (mFileLock) { |
||||||
|
if (mFileWriter == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
StringBuilder builder = new StringBuilder("Nav"); |
||||||
|
builder.append(RECORD_DELIMITER); |
||||||
|
builder.append(navigationMessage.getSvid()); |
||||||
|
builder.append(RECORD_DELIMITER); |
||||||
|
builder.append(navigationMessage.getType()); |
||||||
|
builder.append(RECORD_DELIMITER); |
||||||
|
|
||||||
|
int status = navigationMessage.getStatus(); |
||||||
|
builder.append(status); |
||||||
|
builder.append(RECORD_DELIMITER); |
||||||
|
builder.append(navigationMessage.getMessageId()); |
||||||
|
builder.append(RECORD_DELIMITER); |
||||||
|
builder.append(navigationMessage.getSubmessageId()); |
||||||
|
byte[] data = navigationMessage.getData(); |
||||||
|
for (byte word : data) { |
||||||
|
builder.append(RECORD_DELIMITER); |
||||||
|
builder.append(word); |
||||||
|
} |
||||||
|
try { |
||||||
|
mFileWriter.write(builder.toString()); |
||||||
|
mFileWriter.newLine(); |
||||||
|
} catch (IOException e) { |
||||||
|
logException(ERROR_WRITING_FILE, e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssNavigationMessageStatusChanged(int status) {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssStatusChanged(GnssStatus gnssStatus) {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onNmeaReceived(long timestamp, String s) {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onListenerRegistration(String listener, boolean result) {} |
||||||
|
|
||||||
|
private void writeGnssMeasurementToFile(GnssClock clock, GnssMeasurement measurement) |
||||||
|
throws IOException { |
||||||
|
String clockStream = |
||||||
|
String.format( |
||||||
|
"Raw,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", |
||||||
|
SystemClock.elapsedRealtime(), |
||||||
|
clock.getTimeNanos(), |
||||||
|
clock.hasLeapSecond() ? clock.getLeapSecond() : "", |
||||||
|
clock.hasTimeUncertaintyNanos() ? clock.getTimeUncertaintyNanos() : "", |
||||||
|
clock.getFullBiasNanos(), |
||||||
|
clock.hasBiasNanos() ? clock.getBiasNanos() : "", |
||||||
|
clock.hasBiasUncertaintyNanos() ? clock.getBiasUncertaintyNanos() : "", |
||||||
|
clock.hasDriftNanosPerSecond() ? clock.getDriftNanosPerSecond() : "", |
||||||
|
clock.hasDriftUncertaintyNanosPerSecond() |
||||||
|
? clock.getDriftUncertaintyNanosPerSecond() |
||||||
|
: "", |
||||||
|
clock.getHardwareClockDiscontinuityCount() + ","); |
||||||
|
mFileWriter.write(clockStream); |
||||||
|
|
||||||
|
String measurementStream = |
||||||
|
String.format( |
||||||
|
"%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", |
||||||
|
measurement.getSvid(), |
||||||
|
measurement.getTimeOffsetNanos(), |
||||||
|
measurement.getState(), |
||||||
|
measurement.getReceivedSvTimeNanos(), |
||||||
|
measurement.getReceivedSvTimeUncertaintyNanos(), |
||||||
|
measurement.getCn0DbHz(), |
||||||
|
measurement.getPseudorangeRateMetersPerSecond(), |
||||||
|
measurement.getPseudorangeRateUncertaintyMetersPerSecond(), |
||||||
|
measurement.getAccumulatedDeltaRangeState(), |
||||||
|
measurement.getAccumulatedDeltaRangeMeters(), |
||||||
|
measurement.getAccumulatedDeltaRangeUncertaintyMeters(), |
||||||
|
measurement.hasCarrierFrequencyHz() ? measurement.getCarrierFrequencyHz() : "", |
||||||
|
measurement.hasCarrierCycles() ? measurement.getCarrierCycles() : "", |
||||||
|
measurement.hasCarrierPhase() ? measurement.getCarrierPhase() : "", |
||||||
|
measurement.hasCarrierPhaseUncertainty() |
||||||
|
? measurement.getCarrierPhaseUncertainty() |
||||||
|
: "", |
||||||
|
measurement.getMultipathIndicator(), |
||||||
|
measurement.hasSnrInDb() ? measurement.getSnrInDb() : "", |
||||||
|
measurement.getConstellationType()); |
||||||
|
mFileWriter.write(measurementStream); |
||||||
|
mFileWriter.newLine(); |
||||||
|
} |
||||||
|
|
||||||
|
private void logException(String errorMessage, Exception e) { |
||||||
|
Log.e(GnssContainer.TAG + TAG, errorMessage, e); |
||||||
|
Toast.makeText(mContext, errorMessage, Toast.LENGTH_LONG).show(); |
||||||
|
} |
||||||
|
|
||||||
|
private void logError(String errorMessage) { |
||||||
|
Log.e(GnssContainer.TAG + TAG, errorMessage); |
||||||
|
Toast.makeText(mContext, errorMessage, Toast.LENGTH_LONG).show(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Implements a {@link FileFilter} to delete files that are not in the |
||||||
|
* {@link FileToDeleteFilter#mRetainedFiles}. |
||||||
|
*/ |
||||||
|
private static class FileToDeleteFilter implements FileFilter { |
||||||
|
private final List<File> mRetainedFiles; |
||||||
|
|
||||||
|
public FileToDeleteFilter(File... retainedFiles) { |
||||||
|
this.mRetainedFiles = Arrays.asList(retainedFiles); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns {@code true} to delete the file, and {@code false} to keep the file. |
||||||
|
* |
||||||
|
* <p>Files are deleted if they are not in the {@link FileToDeleteFilter#mRetainedFiles} list. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean accept(File pathname) { |
||||||
|
if (pathname == null || !pathname.exists()) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
if (mRetainedFiles.contains(pathname)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return pathname.length() < MINIMUM_USABLE_FILE_SIZE_BYTES; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,289 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import android.content.Context; |
||||||
|
import android.location.GnssMeasurementsEvent; |
||||||
|
import android.location.GnssNavigationMessage; |
||||||
|
import android.location.GnssStatus; |
||||||
|
import android.location.Location; |
||||||
|
import android.location.LocationListener; |
||||||
|
import android.location.LocationManager; |
||||||
|
import android.location.OnNmeaMessageListener; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.os.SystemClock; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
/** |
||||||
|
* A container for GPS related API calls, it binds the {@link LocationManager} with {@link UiLogger} |
||||||
|
*/ |
||||||
|
public class GnssContainer { |
||||||
|
|
||||||
|
public static final String TAG = "GnssLogger"; |
||||||
|
|
||||||
|
private static final long LOCATION_RATE_GPS_MS = TimeUnit.SECONDS.toMillis(1L); |
||||||
|
private static final long LOCATION_RATE_NETWORK_MS = TimeUnit.SECONDS.toMillis(60L); |
||||||
|
|
||||||
|
private boolean mLogLocations = true; |
||||||
|
private boolean mLogNavigationMessages = true; |
||||||
|
private boolean mLogMeasurements = true; |
||||||
|
private boolean mLogStatuses = true; |
||||||
|
private boolean mLogNmeas = true; |
||||||
|
|
||||||
|
private final List<GnssListener> mLoggers; |
||||||
|
|
||||||
|
private final LocationManager mLocationManager; |
||||||
|
private final LocationListener mLocationListener = |
||||||
|
new LocationListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onProviderEnabled(String provider) { |
||||||
|
if (mLogLocations) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onProviderEnabled(provider); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onProviderDisabled(String provider) { |
||||||
|
if (mLogLocations) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onProviderDisabled(provider); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onLocationChanged(Location location) { |
||||||
|
if (mLogLocations) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onLocationChanged(location); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onStatusChanged(String provider, int status, Bundle extras) { |
||||||
|
if (mLogLocations) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onLocationStatusChanged(provider, status, extras); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final GnssMeasurementsEvent.Callback gnssMeasurementsEventListener = |
||||||
|
new GnssMeasurementsEvent.Callback() { |
||||||
|
@Override |
||||||
|
public void onGnssMeasurementsReceived(GnssMeasurementsEvent event) { |
||||||
|
if (mLogMeasurements) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onGnssMeasurementsReceived(event); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onStatusChanged(int status) { |
||||||
|
if (mLogMeasurements) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onGnssMeasurementsStatusChanged(status); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final GnssNavigationMessage.Callback gnssNavigationMessageListener = |
||||||
|
new GnssNavigationMessage.Callback() { |
||||||
|
@Override |
||||||
|
public void onGnssNavigationMessageReceived(GnssNavigationMessage event) { |
||||||
|
if (mLogNavigationMessages) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onGnssNavigationMessageReceived(event); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onStatusChanged(int status) { |
||||||
|
if (mLogNavigationMessages) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onGnssNavigationMessageStatusChanged(status); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final GnssStatus.Callback gnssStatusListener = |
||||||
|
new GnssStatus.Callback() { |
||||||
|
@Override |
||||||
|
public void onStarted() {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onStopped() {} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onSatelliteStatusChanged(GnssStatus status) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onGnssStatusChanged(status); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
private final OnNmeaMessageListener nmeaListener = |
||||||
|
new OnNmeaMessageListener() { |
||||||
|
@Override |
||||||
|
public void onNmeaMessage(String s, long l) { |
||||||
|
if (mLogNmeas) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onNmeaReceived(l, s); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public GnssContainer(Context context, GnssListener... loggers) { |
||||||
|
this.mLoggers = Arrays.asList(loggers); |
||||||
|
mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); |
||||||
|
} |
||||||
|
|
||||||
|
public LocationManager getLocationManager() { |
||||||
|
return mLocationManager; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLogLocations(boolean value) { |
||||||
|
mLogLocations = value; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean canLogLocations() { |
||||||
|
return mLogLocations; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLogNavigationMessages(boolean value) { |
||||||
|
mLogNavigationMessages = value; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean canLogNavigationMessages() { |
||||||
|
return mLogNavigationMessages; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLogMeasurements(boolean value) { |
||||||
|
mLogMeasurements = value; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean canLogMeasurements() { |
||||||
|
return mLogMeasurements; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLogStatuses(boolean value) { |
||||||
|
mLogStatuses = value; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean canLogStatuses() { |
||||||
|
return mLogStatuses; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLogNmeas(boolean value) { |
||||||
|
mLogNmeas = value; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean canLogNmeas() { |
||||||
|
return mLogNmeas; |
||||||
|
} |
||||||
|
|
||||||
|
public void registerLocation() { |
||||||
|
boolean isGpsProviderEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); |
||||||
|
if (isGpsProviderEnabled) { |
||||||
|
mLocationManager.requestLocationUpdates( |
||||||
|
LocationManager.NETWORK_PROVIDER, |
||||||
|
LOCATION_RATE_NETWORK_MS, |
||||||
|
0.0f /* minDistance */, |
||||||
|
mLocationListener); |
||||||
|
mLocationManager.requestLocationUpdates( |
||||||
|
LocationManager.GPS_PROVIDER, |
||||||
|
LOCATION_RATE_GPS_MS, |
||||||
|
0.0f /* minDistance */, |
||||||
|
mLocationListener); |
||||||
|
} |
||||||
|
logRegistration("LocationUpdates", isGpsProviderEnabled); |
||||||
|
} |
||||||
|
|
||||||
|
public void unregisterLocation() { |
||||||
|
mLocationManager.removeUpdates(mLocationListener); |
||||||
|
} |
||||||
|
|
||||||
|
public void registerMeasurements() { |
||||||
|
logRegistration( |
||||||
|
"GnssMeasurements", |
||||||
|
mLocationManager.registerGnssMeasurementsCallback(gnssMeasurementsEventListener)); |
||||||
|
} |
||||||
|
|
||||||
|
public void unregisterMeasurements() { |
||||||
|
mLocationManager.unregisterGnssMeasurementsCallback(gnssMeasurementsEventListener); |
||||||
|
} |
||||||
|
|
||||||
|
public void registerNavigation() { |
||||||
|
logRegistration( |
||||||
|
"GpsNavigationMessage", |
||||||
|
mLocationManager.registerGnssNavigationMessageCallback(gnssNavigationMessageListener)); |
||||||
|
} |
||||||
|
|
||||||
|
public void unregisterNavigation() { |
||||||
|
mLocationManager.unregisterGnssNavigationMessageCallback(gnssNavigationMessageListener); |
||||||
|
} |
||||||
|
|
||||||
|
public void registerGnssStatus() { |
||||||
|
logRegistration("GnssStatus", mLocationManager.registerGnssStatusCallback(gnssStatusListener)); |
||||||
|
} |
||||||
|
|
||||||
|
public void unregisterGpsStatus() { |
||||||
|
mLocationManager.unregisterGnssStatusCallback(gnssStatusListener); |
||||||
|
} |
||||||
|
|
||||||
|
public void registerNmea() { |
||||||
|
logRegistration("Nmea", mLocationManager.addNmeaListener(nmeaListener)); |
||||||
|
} |
||||||
|
|
||||||
|
public void unregisterNmea() { |
||||||
|
mLocationManager.removeNmeaListener(nmeaListener); |
||||||
|
} |
||||||
|
|
||||||
|
public void registerAll() { |
||||||
|
registerLocation(); |
||||||
|
registerMeasurements(); |
||||||
|
registerNavigation(); |
||||||
|
registerGnssStatus(); |
||||||
|
registerNmea(); |
||||||
|
} |
||||||
|
|
||||||
|
public void unregisterAll() { |
||||||
|
unregisterLocation(); |
||||||
|
unregisterMeasurements(); |
||||||
|
unregisterNavigation(); |
||||||
|
unregisterGpsStatus(); |
||||||
|
unregisterNmea(); |
||||||
|
} |
||||||
|
|
||||||
|
private void logRegistration(String listener, boolean result) { |
||||||
|
for (GnssListener logger : mLoggers) { |
||||||
|
logger.onListenerRegistration(listener, result); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import android.location.GnssMeasurementsEvent; |
||||||
|
import android.location.GnssNavigationMessage; |
||||||
|
import android.location.GnssStatus; |
||||||
|
import android.location.Location; |
||||||
|
import android.location.LocationListener; |
||||||
|
import android.location.OnNmeaMessageListener; |
||||||
|
import android.os.Bundle; |
||||||
|
|
||||||
|
/** A class representing an interface for logging GPS information. */ |
||||||
|
public interface GnssListener { |
||||||
|
|
||||||
|
/** @see LocationListener#onProviderEnabled(String) */ |
||||||
|
void onProviderEnabled(String provider); |
||||||
|
/** @see LocationListener#onProviderDisabled(String) */ |
||||||
|
void onProviderDisabled(String provider); |
||||||
|
/** @see LocationListener#onLocationChanged(Location) */ |
||||||
|
void onLocationChanged(Location location); |
||||||
|
/** @see LocationListener#onStatusChanged(String, int, Bundle) */ |
||||||
|
void onLocationStatusChanged(String provider, int status, Bundle extras); |
||||||
|
/** |
||||||
|
* @see android.location.GnssMeasurementsEvent.Callback# |
||||||
|
* onGnssMeasurementsReceived(GnssMeasurementsEvent) |
||||||
|
*/ |
||||||
|
void onGnssMeasurementsReceived(GnssMeasurementsEvent event); |
||||||
|
/** @see GnssMeasurementsEvent.Callback#onStatusChanged(int) */ |
||||||
|
void onGnssMeasurementsStatusChanged(int status); |
||||||
|
/** |
||||||
|
* @see GnssNavigationMessage.Callback# |
||||||
|
* onGnssNavigationMessageReceived(GnssNavigationMessage) |
||||||
|
*/ |
||||||
|
void onGnssNavigationMessageReceived(GnssNavigationMessage event); |
||||||
|
/** @see GnssNavigationMessage.Callback#onStatusChanged(int) */ |
||||||
|
void onGnssNavigationMessageStatusChanged(int status); |
||||||
|
/** @see GnssStatus.Callback#onSatelliteStatusChanged(GnssStatus) */ |
||||||
|
void onGnssStatusChanged(GnssStatus gnssStatus); |
||||||
|
/** Called when the listener is registered to listen to GNSS events */ |
||||||
|
void onListenerRegistration(String listener, boolean result); |
||||||
|
/** @see OnNmeaMessageListener#onNmeaMessage(String, long) */ |
||||||
|
void onNmeaReceived(long l, String s); |
||||||
|
} |
@ -0,0 +1,83 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import android.app.Dialog; |
||||||
|
import android.content.Context; |
||||||
|
import android.content.Intent; |
||||||
|
import android.net.MailTo; |
||||||
|
import android.net.Uri; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.webkit.WebView; |
||||||
|
import android.webkit.WebViewClient; |
||||||
|
|
||||||
|
public class HelpDialog extends Dialog { |
||||||
|
|
||||||
|
private static Context mContext = null; |
||||||
|
|
||||||
|
public HelpDialog(Context context) { |
||||||
|
super(context); |
||||||
|
mContext = context; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate(Bundle savedInstanceState) { |
||||||
|
setContentView(R.layout.help); |
||||||
|
WebView help = (WebView)findViewById(R.id.helpView); |
||||||
|
help.setWebViewClient(new WebViewClient(){ |
||||||
|
@Override |
||||||
|
public boolean shouldOverrideUrlLoading(WebView view, String url) { |
||||||
|
if(url.startsWith("mailto:")){ |
||||||
|
MailTo mt = MailTo.parse(url); |
||||||
|
Intent emailIntent = new Intent(Intent.ACTION_SEND); |
||||||
|
emailIntent.setType("*/*"); |
||||||
|
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "GNSSLogger Feedback"); |
||||||
|
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { mt.getTo()}); |
||||||
|
emailIntent.putExtra(Intent.EXTRA_TEXT, ""); |
||||||
|
mContext.startActivity(Intent.createChooser(emailIntent, "Send Feedback...")); |
||||||
|
return true; |
||||||
|
} |
||||||
|
else{ |
||||||
|
view.loadUrl(url); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
String helpText = readRawTextFile(R.raw.help_contents); |
||||||
|
help.loadData(helpText, "text/html; charset=utf-8", "utf-8"); |
||||||
|
} |
||||||
|
|
||||||
|
private String readRawTextFile(int id) { |
||||||
|
InputStream inputStream = mContext.getResources().openRawResource(id); |
||||||
|
InputStreamReader in = new InputStreamReader(inputStream); |
||||||
|
BufferedReader buf = new BufferedReader(in); |
||||||
|
String line; |
||||||
|
StringBuilder text = new StringBuilder(); |
||||||
|
try { |
||||||
|
while (( line = buf.readLine()) != null) |
||||||
|
text.append(line); |
||||||
|
} catch (IOException e) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return text.toString(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,163 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.app.Fragment; |
||||||
|
import android.content.Intent; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.text.Editable; |
||||||
|
import android.text.SpannableStringBuilder; |
||||||
|
import android.text.style.ForegroundColorSpan; |
||||||
|
import android.view.LayoutInflater; |
||||||
|
import android.view.View; |
||||||
|
import android.view.View.OnClickListener; |
||||||
|
import android.view.ViewGroup; |
||||||
|
import android.widget.Button; |
||||||
|
import android.widget.ScrollView; |
||||||
|
import android.widget.TextView; |
||||||
|
import android.widget.Toast; |
||||||
|
|
||||||
|
/** The UI fragment that hosts a logging view. */ |
||||||
|
public class LoggerFragment extends Fragment { |
||||||
|
|
||||||
|
private TextView mLogView; |
||||||
|
private ScrollView mScrollView; |
||||||
|
private FileLogger mFileLogger; |
||||||
|
private UiLogger mUiLogger; |
||||||
|
|
||||||
|
private final UIFragmentComponent mUiComponent = new UIFragmentComponent(); |
||||||
|
|
||||||
|
public void setUILogger(UiLogger value) { |
||||||
|
mUiLogger = value; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFileLogger(FileLogger value) { |
||||||
|
mFileLogger = value; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public View onCreateView( |
||||||
|
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { |
||||||
|
View newView = inflater.inflate(R.layout.fragment_log, container, false /* attachToRoot */); |
||||||
|
mLogView = (TextView) newView.findViewById(R.id.log_view); |
||||||
|
mScrollView = (ScrollView) newView.findViewById(R.id.log_scroll); |
||||||
|
|
||||||
|
UiLogger currentUiLogger = mUiLogger; |
||||||
|
if (currentUiLogger != null) { |
||||||
|
currentUiLogger.setUiFragmentComponent(mUiComponent); |
||||||
|
} |
||||||
|
FileLogger currentFileLogger = mFileLogger; |
||||||
|
if (currentFileLogger != null) { |
||||||
|
currentFileLogger.setUiComponent(mUiComponent); |
||||||
|
} |
||||||
|
|
||||||
|
Button start = (Button) newView.findViewById(R.id.start_log); |
||||||
|
start.setOnClickListener( |
||||||
|
new OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View view) { |
||||||
|
mScrollView.fullScroll(View.FOCUS_UP); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
Button end = (Button) newView.findViewById(R.id.end_log); |
||||||
|
end.setOnClickListener( |
||||||
|
new OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View view) { |
||||||
|
mScrollView.fullScroll(View.FOCUS_DOWN); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
Button clear = (Button) newView.findViewById(R.id.clear_log); |
||||||
|
clear.setOnClickListener( |
||||||
|
new OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View view) { |
||||||
|
mLogView.setText(""); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
final Button startLog = (Button) newView.findViewById(R.id.start_logs); |
||||||
|
final Button sendFile = (Button) newView.findViewById(R.id.send_file); |
||||||
|
|
||||||
|
startLog.setOnClickListener( |
||||||
|
new OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View view) { |
||||||
|
startLog.setEnabled(false); |
||||||
|
sendFile.setEnabled(true); |
||||||
|
Toast.makeText(getContext(), "Starting log...", Toast.LENGTH_LONG).show(); |
||||||
|
mFileLogger.startNewLog(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
sendFile.setOnClickListener( |
||||||
|
new OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View view) { |
||||||
|
startLog.setEnabled(true); |
||||||
|
sendFile.setEnabled(false); |
||||||
|
Toast.makeText(getContext(), "Sending file...", Toast.LENGTH_LONG).show(); |
||||||
|
mFileLogger.send(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
return newView; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* A facade for UI and Activity related operations that are required for {@link GnssListener}s. |
||||||
|
*/ |
||||||
|
public class UIFragmentComponent { |
||||||
|
|
||||||
|
private static final int MAX_LENGTH = 12000; |
||||||
|
private static final int LOWER_THRESHOLD = (int) (MAX_LENGTH * 0.5); |
||||||
|
|
||||||
|
public synchronized void logTextFragment(final String tag, final String text, int color) { |
||||||
|
final SpannableStringBuilder builder = new SpannableStringBuilder(); |
||||||
|
builder.append(tag).append(" | ").append(text).append("\n"); |
||||||
|
builder.setSpan( |
||||||
|
new ForegroundColorSpan(color), |
||||||
|
0 /* start */, |
||||||
|
builder.length(), |
||||||
|
SpannableStringBuilder.SPAN_INCLUSIVE_EXCLUSIVE); |
||||||
|
|
||||||
|
Activity activity = getActivity(); |
||||||
|
if (activity == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
activity.runOnUiThread( |
||||||
|
new Runnable() { |
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
mLogView.append(builder); |
||||||
|
Editable editable = mLogView.getEditableText(); |
||||||
|
int length = editable.length(); |
||||||
|
if (length > MAX_LENGTH) { |
||||||
|
editable.delete(0, length - LOWER_THRESHOLD); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
public void startActivity(Intent intent) { |
||||||
|
getActivity().startActivity(intent); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,172 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import android.Manifest; |
||||||
|
import android.app.Activity; |
||||||
|
import android.app.Fragment; |
||||||
|
import android.app.FragmentManager; |
||||||
|
import android.content.pm.PackageManager; |
||||||
|
import android.os.Build; |
||||||
|
import android.os.Build.VERSION_CODES; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.support.design.widget.TabLayout; |
||||||
|
import android.support.design.widget.TabLayout.TabLayoutOnPageChangeListener; |
||||||
|
import android.support.v13.app.FragmentPagerAdapter; |
||||||
|
import android.support.v13.app.FragmentStatePagerAdapter; |
||||||
|
import android.support.v4.app.ActivityCompat; |
||||||
|
import android.support.v4.content.ContextCompat; |
||||||
|
import android.support.v4.view.ViewPager; |
||||||
|
import android.support.v7.app.AppCompatActivity; |
||||||
|
|
||||||
|
import java.util.Locale; |
||||||
|
|
||||||
|
/** The activity for the application. */ |
||||||
|
public class MainActivity extends AppCompatActivity { |
||||||
|
|
||||||
|
private static final int LOCATION_REQUEST_ID = 1; |
||||||
|
private static final String[] REQUIRED_PERMISSIONS = { |
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE |
||||||
|
}; |
||||||
|
private static final int NUMBER_OF_FRAGMENTS = 2; |
||||||
|
private static final int FRAGMENT_INDEX_SETTING = 0; |
||||||
|
private static final int FRAGMENT_INDEX_LOGGER = 1; |
||||||
|
|
||||||
|
private GnssContainer mGnssContainer; |
||||||
|
private UiLogger mUiLogger; |
||||||
|
private FileLogger mFileLogger; |
||||||
|
private Fragment[] mFragments; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onStart() { |
||||||
|
super.onStart(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onCreate(Bundle savedInstanceState) { |
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
setContentView(R.layout.activity_main); |
||||||
|
requestPermissionAndSetupFragments(this); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to one of the |
||||||
|
* sections/tabs/pages. |
||||||
|
*/ |
||||||
|
public class ViewPagerAdapter extends FragmentStatePagerAdapter { |
||||||
|
|
||||||
|
public ViewPagerAdapter(FragmentManager fm) { |
||||||
|
super(fm); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Fragment getItem(int position) { |
||||||
|
switch (position) { |
||||||
|
case FRAGMENT_INDEX_SETTING: |
||||||
|
return mFragments[FRAGMENT_INDEX_SETTING]; |
||||||
|
case FRAGMENT_INDEX_LOGGER: |
||||||
|
return mFragments[FRAGMENT_INDEX_LOGGER]; |
||||||
|
default: |
||||||
|
throw new IllegalArgumentException("Invalid section: " + position); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getCount() { |
||||||
|
// Show total pages.
|
||||||
|
return 2; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public CharSequence getPageTitle(int position) { |
||||||
|
Locale locale = Locale.getDefault(); |
||||||
|
switch (position) { |
||||||
|
case 0: |
||||||
|
return getString(R.string.title_settings).toUpperCase(locale); |
||||||
|
case 1: |
||||||
|
return getString(R.string.title_log).toUpperCase(locale); |
||||||
|
default: |
||||||
|
return super.getPageTitle(position); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onRequestPermissionsResult( |
||||||
|
int requestCode, String permissions[], int[] grantResults) { |
||||||
|
if (requestCode == LOCATION_REQUEST_ID) { |
||||||
|
// If request is cancelled, the result arrays are empty.
|
||||||
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { |
||||||
|
setupFragments(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void setupFragments() { |
||||||
|
mUiLogger = new UiLogger(); |
||||||
|
mFileLogger = new FileLogger(getApplicationContext()); |
||||||
|
mGnssContainer = new GnssContainer(getApplicationContext(), mUiLogger, mFileLogger); |
||||||
|
mFragments = new Fragment[NUMBER_OF_FRAGMENTS]; |
||||||
|
SettingsFragment settingsFragment = new SettingsFragment(); |
||||||
|
settingsFragment.setGpsContainer(mGnssContainer); |
||||||
|
mFragments[FRAGMENT_INDEX_SETTING] = settingsFragment; |
||||||
|
|
||||||
|
LoggerFragment loggerFragment = new LoggerFragment(); |
||||||
|
loggerFragment.setUILogger(mUiLogger); |
||||||
|
loggerFragment.setFileLogger(mFileLogger); |
||||||
|
mFragments[FRAGMENT_INDEX_LOGGER] = loggerFragment; |
||||||
|
|
||||||
|
|
||||||
|
// The viewpager that will host the section contents.
|
||||||
|
ViewPager viewPager = (ViewPager) findViewById(R.id.pager); |
||||||
|
viewPager.setOffscreenPageLimit(2); |
||||||
|
ViewPagerAdapter adapter = new ViewPagerAdapter(getFragmentManager()); |
||||||
|
viewPager.setAdapter(adapter); |
||||||
|
|
||||||
|
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout); |
||||||
|
tabLayout.setTabsFromPagerAdapter(adapter); |
||||||
|
|
||||||
|
// Set a listener via setOnTabSelectedListener(OnTabSelectedListener) to be notified when any
|
||||||
|
// tab's selection state has been changed.
|
||||||
|
tabLayout.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager)); |
||||||
|
|
||||||
|
// Use a TabLayout.TabLayoutOnPageChangeListener to forward the scroll and selection changes to
|
||||||
|
// this layout
|
||||||
|
viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(tabLayout)); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean hasPermissions(Activity activity) { |
||||||
|
if (Build.VERSION.SDK_INT < VERSION_CODES.M) { |
||||||
|
// Permissions granted at install time.
|
||||||
|
return true; |
||||||
|
} |
||||||
|
for (String p : REQUIRED_PERMISSIONS) { |
||||||
|
if (ContextCompat.checkSelfPermission(activity, p) != PackageManager.PERMISSION_GRANTED) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private void requestPermissionAndSetupFragments(final Activity activity) { |
||||||
|
if (hasPermissions(activity)) { |
||||||
|
setupFragments(); |
||||||
|
} else { |
||||||
|
ActivityCompat.requestPermissions(activity, REQUIRED_PERMISSIONS, LOCATION_REQUEST_ID); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,219 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import android.app.Fragment; |
||||||
|
import android.location.LocationManager; |
||||||
|
import android.os.Build; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.util.Log; |
||||||
|
import android.view.LayoutInflater; |
||||||
|
import android.view.View; |
||||||
|
import android.view.ViewGroup; |
||||||
|
import android.widget.CompoundButton; |
||||||
|
import android.widget.CompoundButton.OnCheckedChangeListener; |
||||||
|
import android.widget.Switch; |
||||||
|
import android.widget.TextView; |
||||||
|
import android.widget.Toast; |
||||||
|
import com.google.android.apps.location.gps.gnsslogger.GnssContainer; |
||||||
|
import java.lang.reflect.InvocationTargetException; |
||||||
|
import android.widget.Button; |
||||||
|
|
||||||
|
/** |
||||||
|
* The UI fragment showing a set of configurable settings for the client to request GPS data. |
||||||
|
*/ |
||||||
|
public class SettingsFragment extends Fragment { |
||||||
|
|
||||||
|
public static final String TAG = ":SettingsFragment"; |
||||||
|
private GnssContainer mGpsContainer; |
||||||
|
private HelpDialog helpDialog; |
||||||
|
|
||||||
|
public void setGpsContainer(GnssContainer value) { |
||||||
|
mGpsContainer = value; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public View onCreateView( |
||||||
|
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { |
||||||
|
View view = inflater.inflate(R.layout.fragment_main, container, false /* attachToRoot */); |
||||||
|
|
||||||
|
final Switch registerLocation = (Switch) view.findViewById(R.id.register_location); |
||||||
|
final TextView registerLocationLabel = |
||||||
|
(TextView) view.findViewById(R.id.register_location_label); |
||||||
|
//set the switch to OFF
|
||||||
|
registerLocation.setChecked(false); |
||||||
|
registerLocationLabel.setText("Switch is OFF"); |
||||||
|
registerLocation.setOnCheckedChangeListener( |
||||||
|
new OnCheckedChangeListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
||||||
|
|
||||||
|
if (isChecked) { |
||||||
|
mGpsContainer.registerLocation(); |
||||||
|
registerLocationLabel.setText("Switch is ON"); |
||||||
|
} else { |
||||||
|
mGpsContainer.unregisterLocation(); |
||||||
|
registerLocationLabel.setText("Switch is OFF"); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
final Switch registerMeasurements = (Switch) view.findViewById(R.id.register_measurements); |
||||||
|
final TextView registerMeasurementsLabel = |
||||||
|
(TextView) view.findViewById(R.id.register_measurement_label); |
||||||
|
//set the switch to OFF
|
||||||
|
registerMeasurements.setChecked(false); |
||||||
|
registerMeasurementsLabel.setText("Switch is OFF"); |
||||||
|
registerMeasurements.setOnCheckedChangeListener( |
||||||
|
new OnCheckedChangeListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
||||||
|
|
||||||
|
if (isChecked) { |
||||||
|
mGpsContainer.registerMeasurements(); |
||||||
|
registerMeasurementsLabel.setText("Switch is ON"); |
||||||
|
} else { |
||||||
|
mGpsContainer.unregisterMeasurements(); |
||||||
|
registerMeasurementsLabel.setText("Switch is OFF"); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
final Switch registerNavigation = (Switch) view.findViewById(R.id.register_navigation); |
||||||
|
final TextView registerNavigationLabel = |
||||||
|
(TextView) view.findViewById(R.id.register_navigation_label); |
||||||
|
//set the switch to OFF
|
||||||
|
registerNavigation.setChecked(false); |
||||||
|
registerNavigationLabel.setText("Switch is OFF"); |
||||||
|
registerNavigation.setOnCheckedChangeListener( |
||||||
|
new OnCheckedChangeListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
||||||
|
|
||||||
|
if (isChecked) { |
||||||
|
mGpsContainer.registerNavigation(); |
||||||
|
registerNavigationLabel.setText("Switch is ON"); |
||||||
|
} else { |
||||||
|
mGpsContainer.unregisterNavigation(); |
||||||
|
registerNavigationLabel.setText("Switch is OFF"); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
final Switch registerGpsStatus = (Switch) view.findViewById(R.id.register_status); |
||||||
|
final TextView registerGpsStatusLabel = |
||||||
|
(TextView) view.findViewById(R.id.register_status_label); |
||||||
|
//set the switch to OFF
|
||||||
|
registerGpsStatus.setChecked(false); |
||||||
|
registerGpsStatusLabel.setText("Switch is OFF"); |
||||||
|
registerGpsStatus.setOnCheckedChangeListener( |
||||||
|
new OnCheckedChangeListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
||||||
|
|
||||||
|
if (isChecked) { |
||||||
|
mGpsContainer.registerGnssStatus(); |
||||||
|
registerGpsStatusLabel.setText("Switch is ON"); |
||||||
|
} else { |
||||||
|
mGpsContainer.unregisterGpsStatus(); |
||||||
|
registerGpsStatusLabel.setText("Switch is OFF"); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
final Switch registerNmea = (Switch) view.findViewById(R.id.register_nmea); |
||||||
|
final TextView registerNmeaLabel = (TextView) view.findViewById(R.id.register_nmea_label); |
||||||
|
//set the switch to OFF
|
||||||
|
registerNmea.setChecked(false); |
||||||
|
registerNmeaLabel.setText("Switch is OFF"); |
||||||
|
registerNmea.setOnCheckedChangeListener( |
||||||
|
new OnCheckedChangeListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |
||||||
|
|
||||||
|
if (isChecked) { |
||||||
|
mGpsContainer.registerNmea(); |
||||||
|
registerNmeaLabel.setText("Switch is ON"); |
||||||
|
} else { |
||||||
|
mGpsContainer.unregisterNmea(); |
||||||
|
registerNmeaLabel.setText("Switch is OFF"); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
Button help = (Button) view.findViewById(R.id.help); |
||||||
|
helpDialog = new HelpDialog(getContext()); |
||||||
|
helpDialog.setTitle("Help contents"); |
||||||
|
helpDialog.create(); |
||||||
|
|
||||||
|
help.setOnClickListener(new View.OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View view) { |
||||||
|
helpDialog.show(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
Button exit = (Button) view.findViewById(R.id.exit); |
||||||
|
exit.setOnClickListener(new View.OnClickListener() { |
||||||
|
@Override |
||||||
|
public void onClick(View view) { |
||||||
|
getActivity().finishAffinity(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
TextView swInfo = (TextView) view.findViewById(R.id.sw_info); |
||||||
|
|
||||||
|
java.lang.reflect.Method method; |
||||||
|
LocationManager locationManager = mGpsContainer.getLocationManager(); |
||||||
|
try { |
||||||
|
method = locationManager.getClass().getMethod("getGnssYearOfHardware"); |
||||||
|
int hwYear = (int) method.invoke(locationManager); |
||||||
|
if (hwYear == 0) { |
||||||
|
swInfo.append("HW Year: " + "2015 or older \n"); |
||||||
|
} else { |
||||||
|
swInfo.append("HW Year: " + hwYear + "\n"); |
||||||
|
} |
||||||
|
|
||||||
|
} catch (NoSuchMethodException e) { |
||||||
|
logException("No such method exception: ", e); |
||||||
|
return null; |
||||||
|
} catch (IllegalAccessException e) { |
||||||
|
logException("Illegal Access exception: ", e); |
||||||
|
return null; |
||||||
|
} catch (InvocationTargetException e) { |
||||||
|
logException("Invocation Target Exception: ", e); |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
String platfromVersionString = Build.VERSION.RELEASE; |
||||||
|
swInfo.append("Platform: " + platfromVersionString + "\n"); |
||||||
|
int apiLivelInt = Build.VERSION.SDK_INT; |
||||||
|
swInfo.append("Api Level: " + apiLivelInt); |
||||||
|
|
||||||
|
return view; |
||||||
|
} |
||||||
|
|
||||||
|
private void logException(String errorMessage, Exception e) { |
||||||
|
Log.e(GnssContainer.TAG + TAG, errorMessage, e); |
||||||
|
Toast.makeText(getContext(), errorMessage, Toast.LENGTH_LONG).show(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,220 @@ |
|||||||
|
/* |
||||||
|
* Copyright (C) 2016 The Android Open Source Project |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.google.android.apps.location.gps.gnsslogger; |
||||||
|
|
||||||
|
import android.graphics.Color; |
||||||
|
import android.location.GnssMeasurementsEvent; |
||||||
|
import android.location.GnssNavigationMessage; |
||||||
|
import android.location.GnssStatus; |
||||||
|
import android.location.Location; |
||||||
|
import android.location.LocationProvider; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.util.Log; |
||||||
|
import com.google.android.apps.location.gps.gnsslogger.LoggerFragment.UIFragmentComponent; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
/** |
||||||
|
* A class representing a UI logger for the application. Its responsibility is show information in |
||||||
|
* the UI. |
||||||
|
*/ |
||||||
|
public class UiLogger implements GnssListener { |
||||||
|
|
||||||
|
private static final long EARTH_RADIUS_METERS = 6371000; |
||||||
|
private static final int USED_COLOR = Color.rgb(0x4a, 0x5f, 0x70); |
||||||
|
|
||||||
|
public UiLogger() {} |
||||||
|
|
||||||
|
private UIFragmentComponent mUiFragmentComponent; |
||||||
|
|
||||||
|
public synchronized UIFragmentComponent getUiFragmentComponent() { |
||||||
|
return mUiFragmentComponent; |
||||||
|
} |
||||||
|
|
||||||
|
public synchronized void setUiFragmentComponent(UIFragmentComponent value) { |
||||||
|
mUiFragmentComponent = value; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onProviderEnabled(String provider) { |
||||||
|
logLocationEvent("onProviderEnabled: " + provider); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onProviderDisabled(String provider) { |
||||||
|
logLocationEvent("onProviderDisabled: " + provider); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onLocationChanged(Location location) { |
||||||
|
logLocationEvent("onLocationChanged: " + location); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onLocationStatusChanged(String provider, int status, Bundle extras) { |
||||||
|
String message = |
||||||
|
String.format( |
||||||
|
"onStatusChanged: provider=%s, status=%s, extras=%s", |
||||||
|
provider, locationStatusToString(status), extras); |
||||||
|
logLocationEvent(message); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssMeasurementsReceived(GnssMeasurementsEvent event) { |
||||||
|
logMeasurementEvent("onGnsssMeasurementsReceived: " + event); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssMeasurementsStatusChanged(int status) { |
||||||
|
logMeasurementEvent("onStatusChanged: " + gnssMeasurementsStatusToString(status)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssNavigationMessageReceived(GnssNavigationMessage event) { |
||||||
|
logNavigationMessageEvent("onGnssNavigationMessageReceived: " + event); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssNavigationMessageStatusChanged(int status) { |
||||||
|
logNavigationMessageEvent("onStatusChanged: " + getGnssNavigationMessageStatus(status)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onGnssStatusChanged(GnssStatus gnssStatus) { |
||||||
|
logStatusEvent("onGnssStatusChanged: " + gnssStatusToString(gnssStatus)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onNmeaReceived(long timestamp, String s) { |
||||||
|
logNmeaEvent(String.format("onNmeaReceived: timestamp=%d, %s", timestamp, s)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onListenerRegistration(String listener, boolean result) { |
||||||
|
logEvent("Registration", String.format("add%sListener: %b", listener, result), USED_COLOR); |
||||||
|
} |
||||||
|
|
||||||
|
private void logMeasurementEvent(String event) { |
||||||
|
logEvent("Measurement", event, USED_COLOR); |
||||||
|
} |
||||||
|
|
||||||
|
private void logNavigationMessageEvent(String event) { |
||||||
|
logEvent("NavigationMsg", event, USED_COLOR); |
||||||
|
} |
||||||
|
|
||||||
|
private void logStatusEvent(String event) { |
||||||
|
logEvent("Status", event, USED_COLOR); |
||||||
|
} |
||||||
|
|
||||||
|
private void logNmeaEvent(String event) { |
||||||
|
logEvent("Nmea", event, USED_COLOR); |
||||||
|
} |
||||||
|
|
||||||
|
private void logEvent(String tag, String message, int color) { |
||||||
|
String composedTag = GnssContainer.TAG + tag; |
||||||
|
Log.d(composedTag, message); |
||||||
|
logText(tag, message, color); |
||||||
|
} |
||||||
|
|
||||||
|
private void logText(String tag, String text, int color) { |
||||||
|
UIFragmentComponent component = getUiFragmentComponent(); |
||||||
|
if (component != null) { |
||||||
|
component.logTextFragment(tag, text, color); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String locationStatusToString(int status) { |
||||||
|
switch (status) { |
||||||
|
case LocationProvider.AVAILABLE: |
||||||
|
return "AVAILABLE"; |
||||||
|
case LocationProvider.OUT_OF_SERVICE: |
||||||
|
return "OUT_OF_SERVICE"; |
||||||
|
case LocationProvider.TEMPORARILY_UNAVAILABLE: |
||||||
|
return "TEMPORARILY_UNAVAILABLE"; |
||||||
|
default: |
||||||
|
return "<Unknown>"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String gnssMeasurementsStatusToString(int status) { |
||||||
|
switch (status) { |
||||||
|
case GnssMeasurementsEvent.Callback.STATUS_NOT_SUPPORTED: |
||||||
|
return "NOT_SUPPORTED"; |
||||||
|
case GnssMeasurementsEvent.Callback.STATUS_READY: |
||||||
|
return "READY"; |
||||||
|
case GnssMeasurementsEvent.Callback.STATUS_LOCATION_DISABLED: |
||||||
|
return "GNSS_LOCATION_DISABLED"; |
||||||
|
default: |
||||||
|
return "<Unknown>"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String getGnssNavigationMessageStatus(int status) { |
||||||
|
switch (status) { |
||||||
|
case GnssNavigationMessage.STATUS_UNKNOWN: |
||||||
|
return "Status Unknown"; |
||||||
|
case GnssNavigationMessage.STATUS_PARITY_PASSED: |
||||||
|
return "READY"; |
||||||
|
case GnssNavigationMessage.STATUS_PARITY_REBUILT: |
||||||
|
return "Status Parity Rebuilt"; |
||||||
|
default: |
||||||
|
return "<Unknown>"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String gnssStatusToString(GnssStatus gnssStatus) { |
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder("SATELLITE_STATUS | [Satellites:\n"); |
||||||
|
for (int i = 0; i < gnssStatus.getSatelliteCount(); i++) { |
||||||
|
builder |
||||||
|
.append("Constellation = ") |
||||||
|
.append(getConstellationName(gnssStatus.getConstellationType(i))) |
||||||
|
.append(", "); |
||||||
|
builder.append("Svid = ").append(gnssStatus.getSvid(i)).append(", "); |
||||||
|
builder.append("Cn0DbHz = ").append(gnssStatus.getCn0DbHz(i)).append(", "); |
||||||
|
builder.append("Elevation = ").append(gnssStatus.getElevationDegrees(i)).append(", "); |
||||||
|
builder.append("Azimuth = ").append(gnssStatus.getAzimuthDegrees(i)).append(", "); |
||||||
|
builder.append("hasEphemeris = ").append(gnssStatus.hasEphemerisData(i)).append(", "); |
||||||
|
builder.append("hasAlmanac = ").append(gnssStatus.hasAlmanacData(i)).append(", "); |
||||||
|
builder.append("usedInFix = ").append(gnssStatus.usedInFix(i)).append("\n"); |
||||||
|
} |
||||||
|
builder.append("]"); |
||||||
|
return builder.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
private void logLocationEvent(String event) { |
||||||
|
logEvent("Location", event, USED_COLOR); |
||||||
|
} |
||||||
|
|
||||||
|
private String getConstellationName(int id) { |
||||||
|
switch (id) { |
||||||
|
case 1: |
||||||
|
return "GPS"; |
||||||
|
case 2: |
||||||
|
return "SBAS"; |
||||||
|
case 3: |
||||||
|
return "GLONASS"; |
||||||
|
case 4: |
||||||
|
return "QZSS"; |
||||||
|
case 5: |
||||||
|
return "BEIDOU"; |
||||||
|
case 6: |
||||||
|
return "GALILEO"; |
||||||
|
default: |
||||||
|
return "UNKNOWN"; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 2.1 KiB |
@ -0,0 +1,19 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<android.support.design.widget.TabLayout |
||||||
|
android:id="@+id/tab_layout" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" /> |
||||||
|
|
||||||
|
<android.support.v4.view.ViewPager |
||||||
|
android:id="@+id/pager" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="fill_parent" |
||||||
|
android:layout_below="@id/tab_layout"/> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,67 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:orientation="vertical" > |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
|
||||||
|
<Button |
||||||
|
android:id="@+id/start_log" |
||||||
|
android:text="\u2770 Start" |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" /> |
||||||
|
<Button |
||||||
|
android:id="@+id/clear_log" |
||||||
|
android:text="Clear" |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" /> |
||||||
|
<Button |
||||||
|
android:id="@+id/end_log" |
||||||
|
android:text="End \u2771" |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" /> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<ScrollView |
||||||
|
android:id="@+id/log_scroll" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="0dp" |
||||||
|
android:layout_weight="1"> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/log_view" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" /> |
||||||
|
|
||||||
|
</ScrollView> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
|
||||||
|
<Button |
||||||
|
android:id="@+id/start_logs" |
||||||
|
android:text="Start Log" |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content"/> |
||||||
|
|
||||||
|
<Button |
||||||
|
android:id="@+id/send_file" |
||||||
|
android:text="Stop & Send" |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_weight="1"/> |
||||||
|
|
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,155 @@ |
|||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="match_parent" |
||||||
|
android:orientation="vertical" |
||||||
|
android:paddingLeft="@dimen/activity_horizontal_margin" |
||||||
|
android:paddingRight="@dimen/activity_horizontal_margin" |
||||||
|
android:paddingTop="@dimen/activity_vertical_margin" |
||||||
|
android:paddingBottom="@dimen/activity_vertical_margin" |
||||||
|
tools:context=".MainActivity"> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
<TextView |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:textStyle="bold" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:id="@+id/register_location_label" /> |
||||||
|
<Switch |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:id="@+id/register_location" |
||||||
|
android:singleLine="true" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:text="@string/location_label" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
<TextView |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:textStyle="bold" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:id="@+id/register_measurement_label" /> |
||||||
|
<Switch |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:id="@+id/register_measurements" |
||||||
|
android:singleLine="true" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:text="@string/measurements_label" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
<TextView |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:layout_gravity="center_vertical" |
||||||
|
android:textStyle="bold" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:id="@+id/register_navigation_label" /> |
||||||
|
<Switch |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:id="@+id/register_navigation" |
||||||
|
android:singleLine="true" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:text="@string/nav_msg_label" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
<TextView |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:textStyle="bold" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:id="@+id/register_status_label" /> |
||||||
|
<Switch |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:id="@+id/register_status" |
||||||
|
android:singleLine="true" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:text="@string/gnss_status_label" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
<TextView |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:textStyle="bold" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:id="@+id/register_nmea_label" /> |
||||||
|
<Switch |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:id="@+id/register_nmea" |
||||||
|
android:singleLine="true" |
||||||
|
android:layout_marginTop="15dp" |
||||||
|
android:text="@string/nmea_label" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout |
||||||
|
android:orientation="horizontal" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content"> |
||||||
|
<Button |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/help" |
||||||
|
android:layout_marginTop="150dp" |
||||||
|
android:id="@+id/help" |
||||||
|
android:singleLine="true" /> |
||||||
|
<Button |
||||||
|
android:layout_width="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/exit" |
||||||
|
android:layout_marginTop="150dp" |
||||||
|
android:id="@+id/exit" |
||||||
|
android:singleLine="true" /> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:id="@+id/sw_info" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="0dp" |
||||||
|
android:layout_weight="1" |
||||||
|
android:textStyle="bold" |
||||||
|
android:gravity="bottom"/> |
||||||
|
|
||||||
|
<TextView |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:gravity="end|bottom" |
||||||
|
android:textStyle="italic|bold" |
||||||
|
android:text="@string/app_version"/> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,13 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="fill_parent" |
||||||
|
android:orientation="vertical" > |
||||||
|
|
||||||
|
<android.webkit.WebView |
||||||
|
android:id="@+id/helpView" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="wrap_content" > |
||||||
|
</android.webkit.WebView> |
||||||
|
|
||||||
|
</LinearLayout> |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,20 @@ |
|||||||
|
<a href="#about_apphelp">About AppHelp</a> |
||||||
|
<br> |
||||||
|
<a href="#feedback">Feedback</a> |
||||||
|
<br> |
||||||
|
<a name="about_apphelp" id="about_apphelp"> |
||||||
|
<h3>About AppHelp</h3> |
||||||
|
<ul> |
||||||
|
<li>Start Log button: Starts logging when pushed.</li> |
||||||
|
<li>Stop & Send button: Stops logging and shows dialog to send the file via email or other options.</li> |
||||||
|
</ul> |
||||||
|
|
||||||
|
</a> |
||||||
|
<br> |
||||||
|
<a name="feedback" id="feedback"> |
||||||
|
<h3>Feedback</h3> |
||||||
|
Any comments, feedback, suggestions on GNSSLogger please write to us using the link below. |
||||||
|
<br> |
||||||
|
<a href="mailto:pseudoranges-feedback@google.com">Contact support</a> |
||||||
|
</a> |
||||||
|
<br> |
@ -0,0 +1,6 @@ |
|||||||
|
<resources> |
||||||
|
<!-- Example customization of dimensions originally defined in res/values/dimens.xml |
||||||
|
(such as screen margins) for screens with more than 820dp of available width. This |
||||||
|
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). --> |
||||||
|
<dimen name="activity_horizontal_margin">64dp</dimen> |
||||||
|
</resources> |
@ -0,0 +1,6 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
<color name="colorPrimary">#3F51B5</color> |
||||||
|
<color name="colorPrimaryDark">#303F9F</color> |
||||||
|
<color name="colorAccent">#FF4081</color> |
||||||
|
</resources> |
@ -0,0 +1,6 @@ |
|||||||
|
<resources> |
||||||
|
<!-- Default screen margins, per the Android Design guidelines. --> |
||||||
|
<dimen name="activity_horizontal_margin">16dp</dimen> |
||||||
|
<dimen name="activity_vertical_margin">16dp</dimen> |
||||||
|
<dimen name="button_text_size">12sp</dimen> |
||||||
|
</resources> |
@ -0,0 +1,19 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
|
||||||
|
<string name="app_name">GnssLogger</string> |
||||||
|
<string name="app_version">v1.4.0.0</string> |
||||||
|
|
||||||
|
<string name="title_settings">Settings</string> |
||||||
|
<string name="title_log">Log</string> |
||||||
|
<string name="title_device">Device</string> |
||||||
|
<integer name="google_play_services_version">8487000</integer> |
||||||
|
<string name="location_label">Location</string> |
||||||
|
<string name="measurements_label">Measurements</string> |
||||||
|
<string name="nav_msg_label">Navigation Messages</string> |
||||||
|
<string name="gnss_status_label">GnssStatus</string> |
||||||
|
<string name="nmea_label">Nmea</string> |
||||||
|
<string name="help">HELP</string> |
||||||
|
<string name="exit">Exit</string> |
||||||
|
|
||||||
|
</resources> |
@ -0,0 +1,5 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> |
||||||
|
</style> |
||||||
|
</resources> |
@ -0,0 +1,23 @@ |
|||||||
|
// Top-level build file where you can add configuration options common to all sub-projects/modules. |
||||||
|
|
||||||
|
buildscript { |
||||||
|
repositories { |
||||||
|
jcenter() |
||||||
|
} |
||||||
|
dependencies { |
||||||
|
classpath 'com.android.tools.build:gradle:2.2.0' |
||||||
|
|
||||||
|
// NOTE: Do not place your application dependencies here; they belong |
||||||
|
// in the individual module build.gradle files |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
allprojects { |
||||||
|
repositories { |
||||||
|
jcenter() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
task clean(type: Delete) { |
||||||
|
delete rootProject.buildDir |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
# Project-wide Gradle settings. |
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users: |
||||||
|
# Gradle settings configured through the IDE *will override* |
||||||
|
# any settings specified in this file. |
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit |
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html |
||||||
|
|
||||||
|
# Specifies the JVM arguments used for the daemon process. |
||||||
|
# The setting is particularly useful for tweaking memory settings. |
||||||
|
org.gradle.jvmargs=-Xmx1536m |
||||||
|
|
||||||
|
# When configured, Gradle will run in incubating parallel mode. |
||||||
|
# This option should only be used with decoupled projects. More details, visit |
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects |
||||||
|
# org.gradle.parallel=true |
@ -0,0 +1,160 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
############################################################################## |
||||||
|
## |
||||||
|
## Gradle start up script for UN*X |
||||||
|
## |
||||||
|
############################################################################## |
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||||
|
DEFAULT_JVM_OPTS="" |
||||||
|
|
||||||
|
APP_NAME="Gradle" |
||||||
|
APP_BASE_NAME=`basename "$0"` |
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value. |
||||||
|
MAX_FD="maximum" |
||||||
|
|
||||||
|
warn ( ) { |
||||||
|
echo "$*" |
||||||
|
} |
||||||
|
|
||||||
|
die ( ) { |
||||||
|
echo |
||||||
|
echo "$*" |
||||||
|
echo |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false'). |
||||||
|
cygwin=false |
||||||
|
msys=false |
||||||
|
darwin=false |
||||||
|
case "`uname`" in |
||||||
|
CYGWIN* ) |
||||||
|
cygwin=true |
||||||
|
;; |
||||||
|
Darwin* ) |
||||||
|
darwin=true |
||||||
|
;; |
||||||
|
MINGW* ) |
||||||
|
msys=true |
||||||
|
;; |
||||||
|
esac |
||||||
|
|
||||||
|
# Attempt to set APP_HOME |
||||||
|
# Resolve links: $0 may be a link |
||||||
|
PRG="$0" |
||||||
|
# Need this for relative symlinks. |
||||||
|
while [ -h "$PRG" ] ; do |
||||||
|
ls=`ls -ld "$PRG"` |
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'` |
||||||
|
if expr "$link" : '/.*' > /dev/null; then |
||||||
|
PRG="$link" |
||||||
|
else |
||||||
|
PRG=`dirname "$PRG"`"/$link" |
||||||
|
fi |
||||||
|
done |
||||||
|
SAVED="`pwd`" |
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null |
||||||
|
APP_HOME="`pwd -P`" |
||||||
|
cd "$SAVED" >/dev/null |
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar |
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM. |
||||||
|
if [ -n "$JAVA_HOME" ] ; then |
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then |
||||||
|
# IBM's JDK on AIX uses strange locations for the executables |
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java" |
||||||
|
else |
||||||
|
JAVACMD="$JAVA_HOME/bin/java" |
||||||
|
fi |
||||||
|
if [ ! -x "$JAVACMD" ] ; then |
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME |
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the |
||||||
|
location of your Java installation." |
||||||
|
fi |
||||||
|
else |
||||||
|
JAVACMD="java" |
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the |
||||||
|
location of your Java installation." |
||||||
|
fi |
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can. |
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then |
||||||
|
MAX_FD_LIMIT=`ulimit -H -n` |
||||||
|
if [ $? -eq 0 ] ; then |
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then |
||||||
|
MAX_FD="$MAX_FD_LIMIT" |
||||||
|
fi |
||||||
|
ulimit -n $MAX_FD |
||||||
|
if [ $? -ne 0 ] ; then |
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD" |
||||||
|
fi |
||||||
|
else |
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" |
||||||
|
fi |
||||||
|
fi |
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock |
||||||
|
if $darwin; then |
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" |
||||||
|
fi |
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java |
||||||
|
if $cygwin ; then |
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"` |
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` |
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"` |
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath |
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` |
||||||
|
SEP="" |
||||||
|
for dir in $ROOTDIRSRAW ; do |
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir" |
||||||
|
SEP="|" |
||||||
|
done |
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))" |
||||||
|
# Add a user-defined pattern to the cygpath arguments |
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then |
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" |
||||||
|
fi |
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh |
||||||
|
i=0 |
||||||
|
for arg in "$@" ; do |
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` |
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option |
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition |
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` |
||||||
|
else |
||||||
|
eval `echo args$i`="\"$arg\"" |
||||||
|
fi |
||||||
|
i=$((i+1)) |
||||||
|
done |
||||||
|
case $i in |
||||||
|
(0) set -- ;; |
||||||
|
(1) set -- "$args0" ;; |
||||||
|
(2) set -- "$args0" "$args1" ;; |
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;; |
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;; |
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; |
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; |
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; |
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; |
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; |
||||||
|
esac |
||||||
|
fi |
||||||
|
|
||||||
|
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules |
||||||
|
function splitJvmOpts() { |
||||||
|
JVM_OPTS=("$@") |
||||||
|
} |
||||||
|
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS |
||||||
|
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" |
||||||
|
|
||||||
|
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" |
@ -0,0 +1,90 @@ |
|||||||
|
@if "%DEBUG%" == "" @echo off |
||||||
|
@rem ########################################################################## |
||||||
|
@rem |
||||||
|
@rem Gradle startup script for Windows |
||||||
|
@rem |
||||||
|
@rem ########################################################################## |
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell |
||||||
|
if "%OS%"=="Windows_NT" setlocal |
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. |
||||||
|
set DEFAULT_JVM_OPTS= |
||||||
|
|
||||||
|
set DIRNAME=%~dp0 |
||||||
|
if "%DIRNAME%" == "" set DIRNAME=. |
||||||
|
set APP_BASE_NAME=%~n0 |
||||||
|
set APP_HOME=%DIRNAME% |
||||||
|
|
||||||
|
@rem Find java.exe |
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome |
||||||
|
|
||||||
|
set JAVA_EXE=java.exe |
||||||
|
%JAVA_EXE% -version >NUL 2>&1 |
||||||
|
if "%ERRORLEVEL%" == "0" goto init |
||||||
|
|
||||||
|
echo. |
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. |
||||||
|
echo. |
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the |
||||||
|
echo location of your Java installation. |
||||||
|
|
||||||
|
goto fail |
||||||
|
|
||||||
|
:findJavaFromJavaHome |
||||||
|
set JAVA_HOME=%JAVA_HOME:"=% |
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe |
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init |
||||||
|
|
||||||
|
echo. |
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% |
||||||
|
echo. |
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the |
||||||
|
echo location of your Java installation. |
||||||
|
|
||||||
|
goto fail |
||||||
|
|
||||||
|
:init |
||||||
|
@rem Get command-line arguments, handling Windowz variants |
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args |
||||||
|
if "%@eval[2+2]" == "4" goto 4NT_args |
||||||
|
|
||||||
|
:win9xME_args |
||||||
|
@rem Slurp the command line arguments. |
||||||
|
set CMD_LINE_ARGS= |
||||||
|
set _SKIP=2 |
||||||
|
|
||||||
|
:win9xME_args_slurp |
||||||
|
if "x%~1" == "x" goto execute |
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%* |
||||||
|
goto execute |
||||||
|
|
||||||
|
:4NT_args |
||||||
|
@rem Get arguments from the 4NT Shell from JP Software |
||||||
|
set CMD_LINE_ARGS=%$ |
||||||
|
|
||||||
|
:execute |
||||||
|
@rem Setup the command line |
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar |
||||||
|
|
||||||
|
@rem Execute Gradle |
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% |
||||||
|
|
||||||
|
:end |
||||||
|
@rem End local scope for the variables with windows NT shell |
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd |
||||||
|
|
||||||
|
:fail |
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of |
||||||
|
rem the _cmd.exe /c_ return code! |
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 |
||||||
|
exit /b 1 |
||||||
|
|
||||||
|
:mainEnd |
||||||
|
if "%OS%"=="Windows_NT" endlocal |
||||||
|
|
||||||
|
:omega |
@ -0,0 +1,10 @@ |
|||||||
|
## This file is automatically generated by Android Studio. |
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED! |
||||||
|
# |
||||||
|
# This file should *NOT* be checked into Version Control Systems, |
||||||
|
# as it contains information specific to your local configuration. |
||||||
|
# |
||||||
|
# Location of the SDK. This is only used by Gradle. |
||||||
|
# For customization when using a Version Control System, please read the |
||||||
|
# header note. |
||||||
|
sdk.dir=/media/build/master/prebuilts/fullsdk/linux |
Loading…
Reference in new issue