Jelajahi Sumber

1.封装Android OpenStreetMap。

Pen Li 7 tahun lalu
induk
melakukan
d0e7df1da6
23 mengubah file dengan 835 tambahan dan 3 penghapusan
  1. 1 0
      ApexDrivers/apexmap/.gitignore
  2. 142 0
      ApexDrivers/apexmap/apexmap.iml
  3. 35 0
      ApexDrivers/apexmap/build.gradle
  4. 13 0
      ApexDrivers/apexmap/build/generated/source/buildConfig/debug/redant/usai/com/apexmap/BuildConfig.java
  5. 21 0
      ApexDrivers/apexmap/proguard-rules.pro
  6. 26 0
      ApexDrivers/apexmap/src/androidTest/java/redant/usai/com/apexmap/ExampleInstrumentedTest.java
  7. 2 0
      ApexDrivers/apexmap/src/main/AndroidManifest.xml
  8. 114 0
      ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMapLegalOverlay.java
  9. 41 0
      ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMapTileSource.java
  10. 257 0
      ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMapView.java
  11. 121 0
      ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMarkerInfoWindow.java
  12. TEMPAT SAMPAH
      ApexDrivers/apexmap/src/main/res/drawable-hdpi/map_marker.png
  13. TEMPAT SAMPAH
      ApexDrivers/apexmap/src/main/res/drawable-ldpi/map_marker.png
  14. TEMPAT SAMPAH
      ApexDrivers/apexmap/src/main/res/drawable-mdpi/map_marker.png
  15. TEMPAT SAMPAH
      ApexDrivers/apexmap/src/main/res/drawable-xhdpi/map_marker.png
  16. TEMPAT SAMPAH
      ApexDrivers/apexmap/src/main/res/drawable-xxhdpi/map_marker.png
  17. TEMPAT SAMPAH
      ApexDrivers/apexmap/src/main/res/drawable-xxhdpi/pop_bg9.9.png
  18. 10 0
      ApexDrivers/apexmap/src/main/res/drawable/map_clear_bg.xml
  19. 29 0
      ApexDrivers/apexmap/src/main/res/layout/info_window.xml
  20. 3 0
      ApexDrivers/apexmap/src/main/res/values/strings.xml
  21. 17 0
      ApexDrivers/apexmap/src/test/java/redant/usai/com/apexmap/ExampleUnitTest.java
  22. 2 2
      ApexDrivers/gradle/wrapper/gradle-wrapper.properties
  23. 1 1
      ApexDrivers/settings.gradle

+ 1 - 0
ApexDrivers/apexmap/.gitignore

@@ -0,0 +1 @@
+/build

+ 142 - 0
ApexDrivers/apexmap/apexmap.iml

@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":apexmap" 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=":apexmap" />
+      </configuration>
+    </facet>
+    <facet type="android" name="Android">
+      <configuration>
+        <option name="SELECTED_BUILD_VARIANT" value="debug" />
+        <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" />
+        <option name="PROJECT_TYPE" value="1" />
+      </configuration>
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
+    <output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
+    <output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out" 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/renderscript_source_output_dir/debug/compileDebugRenderscript/out" 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/apt/androidTest/debug" isTestSource="true" generated="true" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" 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/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" 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$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
+      <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/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/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/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/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/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/rs" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
+      <excludeFolder url="file://$MODULE_DIR$/build/generated/not_namespaced_r_class_sources" />
+      <excludeFolder url="file://$MODULE_DIR$/build/generated/source/r" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/aapt_friendly_merged_manifests" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/check_manifest_result" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/compile_only_not_namespaced_r_class_jar" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/full_jar" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/intermediate-jars" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/library_assets" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/library_manifest" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint_jar" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/packaged_res" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/public_res" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
+      <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 27 Platform" jdkType="Android SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-core-utils:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core:1.1.0@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.0@aar" level="project" />
+    <orderEntry type="library" name="Gradle: org.osmdroid:osmdroid-android:6.0.3@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.0@jar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-annotations:27.1.1@jar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel:1.1.0@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test.espresso:espresso-idling-resource:3.0.2@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:runner:1.0.2@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.core:runtime:1.1.0@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: com.squareup:javawriter:2.1.1@jar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable:27.1.1@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test.espresso:espresso-core:3.0.2@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: com.google.code.findbugs:jsr305:2.0.1@jar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12@jar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-core-ui:27.1.1@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3@jar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-compat:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:support-fragment:27.1.1@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: com.android.support.test:monitor:1.0.2@aar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-library:1.3@jar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-integration:1.3@jar" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.support:appcompat-v7:27.1.1@aar" level="project" />
+    <orderEntry type="library" name="Gradle: android.arch.core:common:1.1.0@jar" level="project" />
+    <orderEntry type="library" scope="TEST" name="Gradle: net.sf.kxml:kxml2:2.3.0@jar" level="project" />
+  </component>
+</module>

+ 35 - 0
ApexDrivers/apexmap/build.gradle

@@ -0,0 +1,35 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 27
+
+
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 27
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation 'com.android.support:appcompat-v7:27.1.1'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+    api 'org.osmdroid:osmdroid-android:6.0.3'
+}

+ 13 - 0
ApexDrivers/apexmap/build/generated/source/buildConfig/debug/redant/usai/com/apexmap/BuildConfig.java

@@ -0,0 +1,13 @@
+/**
+ * Automatically generated file. DO NOT MODIFY
+ */
+package redant.usai.com.apexmap;
+
+public final class BuildConfig {
+  public static final boolean DEBUG = Boolean.parseBoolean("true");
+  public static final String APPLICATION_ID = "redant.usai.com.apexmap";
+  public static final String BUILD_TYPE = "debug";
+  public static final String FLAVOR = "";
+  public static final int VERSION_CODE = 1;
+  public static final String VERSION_NAME = "1.0";
+}

+ 21 - 0
ApexDrivers/apexmap/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# 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 *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
ApexDrivers/apexmap/src/androidTest/java/redant/usai/com/apexmap/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package redant.usai.com.apexmap;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("redant.usai.com.apexmap.test", appContext.getPackageName());
+    }
+}

+ 2 - 0
ApexDrivers/apexmap/src/main/AndroidManifest.xml

@@ -0,0 +1,2 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="redant.usai.com.apexmap"/>

+ 114 - 0
ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMapLegalOverlay.java

@@ -0,0 +1,114 @@
+package redant.usai.com.apexmap.mapkit;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.overlay.Overlay;
+
+public class ApexMapLegalOverlay extends Overlay {
+
+    private final static String OpenStreetMapTitle = "OpenStreetMap";
+
+    private class TextRect {
+        float x, y;
+        int width, height;
+
+        private TextRect(float x, float y, int width, int height) {
+            this.x = x;
+            this.y = y;
+            this.width = width;
+            this.height = height;
+        }
+
+        private boolean containsPoint(float x, float y) {
+
+            float left = this.x;
+            float top = this.y;
+            float right = this.x + this.width;
+            float bottom = this.y + this.height;
+
+            if (x >= left && x <= right && y >= top && y <= bottom) {
+                return true;
+            }
+
+            return false;
+        }
+    }
+
+    public interface LegalClickListener {
+        void legalTextDidClick(ApexMapLegalOverlay overlay);
+    }
+
+    private Paint textPaint;
+    private TextRect textRect;
+    private LegalClickListener listener;
+
+    public ApexMapLegalOverlay(MapView mapView) {
+
+        Context context = mapView.getContext();
+        final DisplayMetrics dm = context.getResources().getDisplayMetrics();
+
+        textPaint = new Paint();
+        textPaint.setColor(Color.BLACK);
+        textPaint.setTextSize(12 * dm.density);
+        textPaint.setStyle(Paint.Style.FILL);
+        textPaint.setAntiAlias(true);
+        //该方法即为设置基线上那个点到底是left,center,还是right  这里我设置为center
+        textPaint.setTextAlign(Paint.Align.CENTER);
+    }
+
+    @Override
+    public void draw(Canvas c, MapView mapView, boolean shadow) {
+
+        int _mapWidt = mapView.getWidth();
+        int _mapHeight = mapView.getHeight();
+
+        Rect rect = new Rect();
+        String text = OpenStreetMapTitle;
+        textPaint.getTextBounds(text, 0, text.length(), rect);
+        int width = rect.width();// 文字宽
+        int height = rect.height();// 文字高
+
+        float x = 10 + width * 0.5f;
+        float y = _mapHeight - height - 10;
+
+        textRect = new TextRect(x, y , width, height);
+
+        c.drawText(text, x, y + height * 0.5f, textPaint);
+    }
+
+    @Override
+    public boolean onSingleTapConfirmed(MotionEvent e, MapView mapView) {
+
+        float x = e.getX();
+        float y = e.getY();
+
+        if (textRect != null && textRect.containsPoint(x, y)) {
+            legalTextDidClick();
+            return true;
+        } else {
+            return super.onSingleTapConfirmed(e, mapView);
+        }
+    }
+
+    public void setListener(LegalClickListener listener) {
+        this.listener = listener;
+    }
+
+    public LegalClickListener getListener() {
+        return listener;
+    }
+
+    private void legalTextDidClick() {
+
+        if (listener != null) {
+            listener.legalTextDidClick(this);
+        }
+    }
+}

+ 41 - 0
ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMapTileSource.java

@@ -0,0 +1,41 @@
+package redant.usai.com.apexmap.mapkit;
+
+import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase;
+import org.osmdroid.util.MapTileIndex;
+
+public class ApexMapTileSource extends OnlineTileSourceBase {
+
+
+    public static ApexMapTileSource defaultTileSource() {
+
+        ApexMapTileSource tileSource = new ApexMapTileSource("ApexTileNormal", 1, 18, 256, ".png", null);
+        return tileSource;
+    }
+
+    /**
+     * @param aName                a human-friendly name for this tile source  自定图源义名字,会在手机外部存储中新建以该名字命名的文件夹,瓦片存储在其中
+     * @param aZoomMinLevel        the minimum zoom level this tile source can provide  最小缩放级别
+     * @param aZoomMaxLevel        the maximum zoom level this tile source can provide  最大缩放级别
+     * @param aTileSizePixels      the tile size in pixels this tile source provides  瓦片质量 (256)
+     * @param aImageFilenameEnding the file name extension used when constructing the filename  瓦片格式(jpg[有损压缩率高、不透明]、png[无损、透明])
+     * @param aBaseUrl             the base url(s) of the tile server used when constructing the url to download the tiles  下载瓦片的链接(前缀)
+     */
+
+    private ApexMapTileSource(String aName, int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels, String aImageFilenameEnding, String[] aBaseUrl) {
+        super(aName, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding, aBaseUrl);
+    }
+
+    private ApexMapTileSource(String aName, int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels, String aImageFilenameEnding, String[] aBaseUrl, String copyyright) {
+        super(aName, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels, aImageFilenameEnding, aBaseUrl, copyyright);
+    }
+
+    @Override
+    public String getTileURLString(long pMapTileIndex) {
+
+        int x = MapTileIndex.getX(pMapTileIndex);
+        int y = MapTileIndex.getY(pMapTileIndex);
+        int z = MapTileIndex.getZoom(pMapTileIndex);
+
+        return String.format("https://map.apexshipping.com/osm_tiles/%d/%d/%d.png",z, x, y);
+    }
+}

+ 257 - 0
ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMapView.java

@@ -0,0 +1,257 @@
+package redant.usai.com.apexmap.mapkit;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+import org.osmdroid.tileprovider.MapTileProviderBase;
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
+import org.osmdroid.util.GeoPoint;
+import org.osmdroid.util.TileSystem;
+import org.osmdroid.views.CustomZoomButtonsController;
+import org.osmdroid.views.MapController;
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.overlay.Marker;
+import org.osmdroid.views.overlay.ScaleBarOverlay;
+import org.osmdroid.views.overlay.compass.CompassOverlay;
+import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider;
+import org.osmdroid.views.overlay.infowindow.InfoWindow;
+
+import java.util.ArrayList;
+
+import redant.usai.com.apexmap.R;
+
+public class ApexMapView extends MapView implements ApexMapLegalOverlay.LegalClickListener {
+
+    // region Initial
+
+    private final static String OpenStreetMapCopyright = "https://www.openstreetmap.org/copyright";
+
+    private ApexMapView self = this;
+
+    public ApexMapView(Context context, MapTileProviderBase tileProvider, Handler tileRequestCompleteHandler, AttributeSet attrs) {
+        super(context, tileProvider, tileRequestCompleteHandler, attrs);
+        initSetting();
+    }
+
+    public ApexMapView(Context context, MapTileProviderBase tileProvider, Handler tileRequestCompleteHandler, AttributeSet attrs, boolean hardwareAccelerated) {
+        super(context, tileProvider, tileRequestCompleteHandler, attrs, hardwareAccelerated);
+        initSetting();
+    }
+
+    public ApexMapView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initSetting();
+    }
+
+    public ApexMapView(Context context) {
+        super(context);
+        initSetting();
+    }
+
+    public ApexMapView(Context context, MapTileProviderBase aTileProvider) {
+        super(context, aTileProvider);
+        initSetting();
+    }
+
+    public ApexMapView(Context context, MapTileProviderBase aTileProvider, Handler tileRequestCompleteHandler) {
+        super(context, aTileProvider, tileRequestCompleteHandler);
+        initSetting();
+    }
+
+    public void initSetting() {
+
+        // legal
+        setupLegalView();
+
+        // 设置图源
+//        setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE);
+
+        ApexMapTileSource tileSource = ApexMapTileSource.defaultTileSource();
+        setTileSource(tileSource);
+
+        // 地图适应不同像素密度
+        setTilesScaledToDpi(true);
+
+        // 主动修改瓦片缩放大小
+        float density = getResources().getDisplayMetrics().density;
+        if (density > 1) {
+            density = (density - 1) * 0.6f + 1;
+        } else {
+            density = 1;
+        }
+        int tile_size = (int) (density * 256);
+        TileSystem.setTileSize(tile_size);
+
+
+
+        // 设置指南针
+        showCompass(getContext());
+
+        // 添加比例尺
+        ScaleBarOverlay mScaleBarOverlay = new ScaleBarOverlay(self);
+        getOverlays().add(mScaleBarOverlay);
+
+        // 设置地图中心
+       setCenter(39.9074647400,116.3912822800); // 天安门
+
+        setUseDataConnection(true);
+
+        // 设置缩放级别
+        setZoomLevel(4);
+        setMinZoomLevel(1.2370782837064525);
+        setMaxZoomLevel(18.0);
+
+        // 垂直滑动范围
+        setScrollableAreaLimitLatitude(MapView.getTileSystem().getMaxLatitude(), MapView.getTileSystem().getMinLatitude(), 0);
+
+        // 设置缩放按钮可见
+//        mMapView.setBuiltInZoomControls(true);
+        getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
+
+        // 设置多指触控可用
+        setMultiTouchControls(true);
+
+    }
+
+    private void setupLegalView() {
+
+        ApexMapLegalOverlay overlay = new ApexMapLegalOverlay(self);
+        overlay.setListener(self);
+        getOverlays().add(overlay);
+    }
+
+    // endregion
+
+    // region Setter
+
+    // 添加指南针
+    private CompassOverlay mCompassOverlay;
+    public void showCompass(Context context) {
+        if (context != null && mCompassOverlay == null) {
+            mCompassOverlay = new CompassOverlay(context, new InternalCompassOrientationProvider(context), self);
+            getOverlays().add(mCompassOverlay);
+            mCompassOverlay.enableCompass();
+        }
+    }
+
+    public void hideCompass() {
+        if (mCompassOverlay != null) {
+            mCompassOverlay.disableCompass();
+            getOverlays().remove(mCompassOverlay);
+        }
+    }
+
+    public Marker addMarker(GeoPoint geoPoint, String title, String description) {
+
+        if (geoPoint != null) {
+            // 添加Marker
+            Marker marker = new Marker(self);
+            marker.setIcon(getResources().getDrawable(R.drawable.map_marker));//设置图标
+            marker.setPosition(geoPoint);//设置位置
+            marker.setAnchor(0, 0);//设置偏移量
+            marker.setTitle(title);//设置标题
+            marker.setSubDescription(description);//设置说明
+
+            getOverlays().add(marker);//添加marker到MapView
+
+            return marker;
+        }
+        return null;
+    }
+
+    public ApexMarkerInfoWindow addWindowInfoForMarker(Marker marker, Object attachment, ApexMarkerInfoWindow.ApexMarkerInfoWindowClickListener listener) {
+        if (marker != null) {
+            ApexMarkerInfoWindow infoWindow = new ApexMarkerInfoWindow(self, attachment);
+            infoWindow.setClickListener(listener);
+            marker.setInfoWindow(infoWindow);
+            return infoWindow;
+        }
+        return null;
+    }
+
+    public void setCenter(double latitude, double longitude) {
+
+        GeoPoint geopoint = new GeoPoint(latitude, longitude);
+        MapController mMapController= (MapController) self.getController();//获取MapView控制器
+        mMapController.setCenter(geopoint);//设置地图中心
+
+    }
+
+    public void setZoomLevel(int level) {
+        MapController mMapController= (MapController) self.getController();//获取MapView控制器
+        mMapController.setZoom(level);
+    }
+
+    // endregion
+
+    // region Getter
+
+    public ArrayList<InfoWindow> getOpenedInfoWindowsOn() {
+
+        int count = self.getChildCount();
+        ArrayList<InfoWindow> opened = new ArrayList<InfoWindow>(count);
+        for (int i = 0; i < count; i++) {
+            final View child = self.getChildAt(i);
+            Object tag = child.getTag();
+            if (tag != null && tag instanceof InfoWindow) {
+                InfoWindow infoWindow = (InfoWindow) tag;
+                opened.add(infoWindow);
+            }
+        }
+        return opened;
+    }
+
+    // endregion
+
+    // region Touch
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+
+        ArrayList<InfoWindow> opened = getOpenedInfoWindowsOn();
+        if (opened != null && opened.size() > 0) {
+            for (InfoWindow infoWindow : opened) {
+                infoWindow.close();
+            }
+            return false;
+        }
+
+        return super.dispatchTouchEvent(event);
+    }
+
+    @Override
+    public void legalTextDidClick(ApexMapLegalOverlay overlay) {
+
+        Uri uri = Uri.parse(OpenStreetMapCopyright);
+        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+        getContext().startActivity(intent);
+    }
+
+
+    // endregion
+
+    // region Mask
+
+    private class ApexMapMaskView extends RelativeLayout {
+
+        public ApexMapMaskView(Context context) {
+            super(context);
+        }
+
+        public ApexMapMaskView(Context context, AttributeSet attrs) {
+            super(context, attrs);
+        }
+
+        public ApexMapMaskView(Context context, AttributeSet attrs, int defStyleAttr) {
+            super(context, attrs, defStyleAttr);
+        }
+    }
+
+    // endregion
+}

+ 121 - 0
ApexDrivers/apexmap/src/main/java/redant/usai/com/apexmap/mapkit/ApexMarkerInfoWindow.java

@@ -0,0 +1,121 @@
+package redant.usai.com.apexmap.mapkit;
+
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TextView;
+
+import org.osmdroid.api.IMapView;
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.overlay.OverlayWithIW;
+import org.osmdroid.views.overlay.infowindow.InfoWindow;
+import org.osmdroid.views.overlay.infowindow.MarkerInfoWindow;
+
+import redant.usai.com.apexmap.R;
+
+public class ApexMarkerInfoWindow extends MarkerInfoWindow {
+
+    // region Initial
+    private Object mAttachment;
+    private TextView mTitleTv, mInfoTv;
+    private ApexMarkerInfoWindowClickListener mClickListener;
+    private ApexMarkerInfoWindow self = this;
+
+    public ApexMarkerInfoWindow(MapView mapView, Object attachment) {
+        this(R.layout.info_window, mapView);
+
+        setAttachment(attachment);
+        initBubble();
+    }
+
+    private ApexMarkerInfoWindow(int layoutResId, MapView mapView) {
+        super(layoutResId, mapView);
+    }
+
+    private void initBubble() {
+
+        mTitleTv = getView().findViewById(R.id.tv_title);
+        mInfoTv = getView().findViewById(R.id.tv_info);
+
+        mView.setOnTouchListener(new View.OnTouchListener() {
+            @Override public boolean onTouch(View v, MotionEvent e) {
+                if (e.getAction() == MotionEvent.ACTION_UP) {
+                    close();
+                    if (mClickListener != null) {
+                        mClickListener.onMarkerInfoWindowDidClick(self, mAttachment);
+                    }
+                }
+                return true;
+            }
+        });
+
+    }
+
+    // endregion
+
+    // region Setter
+
+
+    private void setAttachment(Object mAttachment) {
+        this.mAttachment = mAttachment;
+    }
+
+    public void setClickListener(ApexMarkerInfoWindowClickListener listener) {
+        mClickListener = listener;
+    }
+
+    // endregion
+
+    // region Getter
+
+    public ApexMarkerInfoWindowClickListener getClickListener() {
+        return mClickListener;
+    }
+
+    public Object getAttachment() {
+        return mAttachment;
+    }
+
+    // endregion
+
+    // region Action
+    @Override
+    public void onOpen(Object item) {
+
+        // 关闭其他Info Window
+        InfoWindow.closeAllInfoWindowsOn(getMapView());
+
+        if (mView==null) {
+            Log.w(IMapView.LOGTAG, "Error trapped, BasicInfoWindow.open, mView is null!");
+            return;
+        }
+
+        OverlayWithIW overlay = (OverlayWithIW)item;
+        String title = overlay.getTitle();
+        if (title == null)
+            title = "";
+
+        String description = overlay.getSubDescription();
+        if (description == null)
+            description = "";
+
+
+        mTitleTv.setText(title);
+        mInfoTv.setText(description);
+    }
+
+    @Override
+    public void onClose() {
+        super.onClose();
+    }
+    // endregion
+
+    // region Info Window Click Delegate
+
+    public interface ApexMarkerInfoWindowClickListener {
+
+        void onMarkerInfoWindowDidClick(ApexMarkerInfoWindow infoWindow, Object attachment);
+    }
+
+    // endregion
+}

TEMPAT SAMPAH
ApexDrivers/apexmap/src/main/res/drawable-hdpi/map_marker.png


TEMPAT SAMPAH
ApexDrivers/apexmap/src/main/res/drawable-ldpi/map_marker.png


TEMPAT SAMPAH
ApexDrivers/apexmap/src/main/res/drawable-mdpi/map_marker.png


TEMPAT SAMPAH
ApexDrivers/apexmap/src/main/res/drawable-xhdpi/map_marker.png


TEMPAT SAMPAH
ApexDrivers/apexmap/src/main/res/drawable-xxhdpi/map_marker.png


TEMPAT SAMPAH
ApexDrivers/apexmap/src/main/res/drawable-xxhdpi/pop_bg9.9.png


+ 10 - 0
ApexDrivers/apexmap/src/main/res/drawable/map_clear_bg.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <solid
+        android:color="#00000000"
+        >
+
+    </solid>
+
+</shape>

+ 29 - 0
ApexDrivers/apexmap/src/main/res/layout/info_window.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                                          android:id="@+id/popinfo"
+                                          android:layout_width="wrap_content"
+                                          android:layout_height="wrap_content"
+                                          android:orientation="vertical"
+                                          android:background="@drawable/pop_bg9"
+                                          android:paddingLeft="5dp"
+                                          android:paddingRight="5dp"
+                                          android:paddingTop="5dp"
+                                          android:paddingBottom="20dp">
+
+    <TextView
+        android:id="@+id/tv_title"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:textSize="14sp"
+        android:textStyle="bold" />
+
+    <TextView
+        android:gravity="center"
+        android:id="@+id/tv_info"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:textSize="12sp" />
+
+
+</LinearLayout>

+ 3 - 0
ApexDrivers/apexmap/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">ApexMap</string>
+</resources>

+ 17 - 0
ApexDrivers/apexmap/src/test/java/redant/usai/com/apexmap/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package redant.usai.com.apexmap;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 2 - 2
ApexDrivers/gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Wed Dec 05 10:39:45 CST 2018
+#Fri Jan 18 14:39:28 CST 2019
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip

+ 1 - 1
ApexDrivers/settings.gradle

@@ -1 +1 @@
-include ':apexdriverslib', ':apexdriverscn', ':apexdriversi', ':apexcrm', ':RAUtilsLibrary', ':raimage', ':apexmobile'
+include ':apexdriverslib', ':apexdriverscn', ':apexdriversi', ':apexcrm', ':RAUtilsLibrary', ':raimage', ':apexmobile', ':apexmap'