Giải pháp cho ứng dụng bản đồ Android với sử dụng ngoại tuyến?


14

Tôi đang tìm cách phát triển một ứng dụng cho Android với các bản đồ nhúng có thể hoạt động mà không cần kết nối internet (tức là tôi có thể lấy các ô của sơ đồ đường phố mở để sử dụng ngoại tuyến không?).

Tôi đã phát triển các ứng dụng web trước đây bằng cách sử dụng google maps api v3. Tôi cần một câu trả lời chung chung như một câu trả lời cụ thể. Tôi đang cố gắng tìm các khái niệm và công nghệ tôi cần học :)

(Trong khi đó tôi tìm thấy osmdroid. Nó có hoạt động không?)


Điều này không thực sự trả lời câu hỏi. Nếu bạn có một câu hỏi khác, bạn có thể hỏi nó bằng cách nhấp vào Đặt câu hỏi . Bạn cũng có thể thêm tiền thưởng để thu hút sự chú ý hơn cho câu hỏi này một khi bạn có đủ danh tiếng .
Jason Scheirer

Osmand không cho phép nhập bất kỳ bản đồ tùy chỉnh nào theo ý muốn của người dùng nhưng nó chỉ cho phép tải xuống bản đồ trực tiếp từ ứng dụng để sử dụng ngoại tuyến. Như trong trường hợp của tôi, tôi cần phủ lớp phủ trên cùng (bản đồ Raster) đã được chuyển đổi thành * .kmz. Yêu cầu của tôi là sử dụng ngoại tuyến. Tôi đang tìm kiếm một hướng dẫn thích hợp để phát triển ứng dụng android hỗ trợ bản đồ ngoại tuyến như vậy.
hàng

Điều này không thực sự trả lời câu hỏi ban đầu về vị trí và cách lấy bản đồ để sử dụng ngoại tuyến.
MaryBeth

Điều này không thực sự trả lời câu hỏi. Nếu bạn có một câu hỏi khác, bạn có thể hỏi nó bằng cách nhấp vào Đặt câu hỏi . Bạn cũng có thể thêm tiền thưởng để thu hút sự chú ý hơn cho câu hỏi này một khi bạn có đủ danh tiếng . - Từ đánh giá
John Powell

Câu trả lời:



13

Tôi đã thực hiện bản đồ ngoại tuyến bằng SDK Android ESRI và lớp xếp tùy chỉnh. Tôi đã sử dụng máy chủ ArcGIS để tạo bộ đệm dựa trên bản đồ ô vuông, sau đó chèn các ô đó vào cơ sở dữ liệu SQLite và truy vấn chúng dựa trên hàng và cột từ đó. Nó hoạt động rất tốt và nếu bạn cần bản đồ tùy chỉnh từ đầu đến cuối, đó là một phương pháp rất có thể sử dụng.

package com.main.utilinspect;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.List;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonParser;

import android.content.Context;
import android.util.Log;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.esri.core.internal.c.d;
import com.esri.core.internal.c.h;
import com.esri.core.internal.c.l;

import com.esri.android.map.TiledServiceLayer;

public class OfflineDbTiledLayer extends TiledServiceLayer {

File workingDirectory;
String mapDefinition;
String databaseName;
private SQLiteDatabase database;
File blankImage;

byte[] blankImageBytes;

private final Object lock = new Object();


private static final String TAG = "OfflineTiledLayer";  


public OfflineDbTiledLayer(Context paramContext, File workingDirectory, String mapDefinition, String databaseName)  {
    super("required");
    this.workingDirectory = workingDirectory;
    this.mapDefinition = mapDefinition;
    this.databaseName = databaseName;

    String databasePath = workingDirectory.getAbsolutePath() + File.separator + databaseName;

    this.database = SQLiteDatabase.openDatabase(databasePath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 

    this.blankImage = new File(workingDirectory.getAbsolutePath() + File.separator + "blank.png");

    RandomAccessFile raFile = null;

    try {
        raFile = new RandomAccessFile(this.blankImage, "r");

        blankImageBytes = new byte[(int) raFile.length()];
        raFile.readFully(blankImageBytes);

    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       
    finally {
        if(raFile != null) {
            try {
                raFile.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }   

    h h1 = null;

    try
    {

    JsonParser paramJsonParser = new JsonFactory()
    .createJsonParser(new File(workingDirectory.getAbsolutePath() + File.separator + mapDefinition));
    paramJsonParser.nextToken();    

    h1 = h.a(paramJsonParser, "test");
    }
    catch(Exception ex){

    }       


    setFullExtent(h1.f());      
    setDefaultSpatialReference(h1.c());
    setInitialExtent(h1.e());

    l l1;
    List list;
    int i;
    double ad[] = new double[i = (list = (l1 = h1.d()).h).size()];
    double ad1[] = new double[i];
    for(int j = 0; j < list.size(); j++)
    {
        ad[j] = ((d)list.get(j)).b();
        ad1[j] = ((d)list.get(j)).a();
    }

    setTileInfo(new com.esri.android.map.TiledServiceLayer.TileInfo(l1.f, ad, ad1, i, l1.c, l1.b, l1.a));

    super.initLayer();
    return;     
}   

private void openDatabase(){
    if(!database.isOpen()){
        String databasePath = workingDirectory.getAbsolutePath() + File.separator + databaseName;
        this.database = SQLiteDatabase.openDatabase(databasePath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
    }
}

private void closeDatabase(){
    if(database.isOpen()){
        this.database.close();
    }
}

@Override
protected byte[] getTile(int level, int column, int row) throws Exception {
    byte[] tileImage;       

    Log.i(TAG, "getTile");

    Log.i(TAG, "getTile - retrieving tile");            

    synchronized(lock) {

        Log.i(TAG, "getTile - entered synchronized block");

        openDatabase();     

        // First check to see if the tile exists in the database
        Cursor tileCursor = database.rawQuery("SELECT image FROM tiles WHERE level = " + Integer.toString(level) + " AND row = " + Integer.toString(row) + " AND column = " + Integer.toString(column), null);

        if(tileCursor != null && tileCursor.getCount() > 0) {
            tileCursor.moveToFirst();
            tileImage = tileCursor.getBlob(0);
            Log.i(TAG, "getTile - tile found, returning image");                        
        }
        else {
            // The tile does not exist in the database, read the blank placeholder tile and serve it
            tileImage = blankImageBytes;
            Log.i(TAG, "getTile - tile not found returning blank");
        }   

        tileCursor.close();     
        this.database.close();
    }

    Log.i(TAG, "getTile - exited synchronized block");

    return tileImage;   
}

}


Bạn có thể vui lòng chia sẻ một số mã?
gregm

Tôi đã thêm lớp lớp tùy chỉnh của tôi mà làm việc.
eptiliom

7

Tôi đã phát triển một ứng dụng với bản đồ ngoại tuyến cho Android. Miễn phí duy nhất cụ bạn muốn sử dụng là OSMDroid, nếu không thì ESRI. API OSMDroid giống hệt với Google, vì vậy trong trường hợp bạn muốn chuyển đổi từ cái này sang cái khác, thật dễ dàng.

Hãy xem bài đăng này , với một mẫu về cách tích hợp Google Maps vào OSMDroid (nó cũng cung cấp cho bạn ý tưởng về cách sử dụng nó nói chung).


2

Có một ứng dụng tuyệt vời gọi là xGPS cho iPhone và các thiết bị khác. Bạn có thể muốn xem xét điều đó để lấy ý tưởng vì nó cho phép người dùng lưu trước bộ đệm mà họ cần. Tôi sử dụng nó khi tôi ở sâu trong bụi rậm ở Châu Phi, Florida Everglades, chèo thuyền hoặc bất cứ nơi nào tôi không có vùng phủ sóng điện thoại di động. Tôi sẽ lưu trữ bản đồ trước chuyến đi và sau đó có thể sử dụng GPS trên iphone của tôi một cách bình thường mà KHÔNG CÓ INTERNET.

Về cơ bản những gì họ xGPS làm và những gì bạn muốn làm là lưu trữ các ô bản đồ cục bộ trên điện thoại của bạn. Không gian trên các điện thoại di động bị hạn chế. Có ngay cả khi bạn có 32gb trên điện thoại, nó có thể chỉ đủ để lưu trữ một quốc gia nhỏ trên tất cả các mức thu phóng (tỷ lệ). Không ai trong số những điện thoại này (trừ khi bằng cách nào đó được gắn vào bộ nhớ ngoài) sẽ có đủ không gian để lưu trữ thế giới ở tất cả các mức thu phóng. Tôi tưởng tượng điều này sẽ yêu cầu lưu trữ petabyte.

Vì vậy, bạn cần có thể yêu cầu người dùng của mình lưu trữ "vùng" hoặc bản đồ khi anh ấy trực tuyến để anh ấy có thể sử dụng chúng ngoại tuyến. Với xGPS, tôi có thể vẽ một đa giác trên vùng quan tâm của mình và chỉ định mức thu phóng nào tôi muốn lưu vào bộ đệm. Sau đó, nó sẽ bắt đầu tải tất cả cho tôi về điện thoại của tôi, từ chính điện thoại hoặc chương trình trên máy tính của tôi. Sau đó, có một nút trên ứng dụng cho phép tôi chuyển sang chế độ "ngoại tuyến" khi tôi mất kết nối internet.


2

Hãy thử sử dụng SDK di động NextGIS. Chế độ trực tuyến / ngoại tuyến bao gồm chỉnh sửa và tự động đồng bộ hóa với máy chủ (NextGIS Web). Các lớp raster và vector, các hình thức nhập tùy chỉnh, tất cả các loại hỗ trợ hình học.

Một ứng dụng ví dụ NextGIS Mobile có thể được tìm thấy trong cửa hàng Google Play - https://play.google.com/store/apps/details?id=com.nextgis.mobile

Nguồn ở đây: https://github.com/nextgis/android_gisapp

Tài liệu: http://docs.nextgis.com/docs_ngmobile/source/toc.html

Một ứng dụng đơn giản khác có tại đây: https://github.com/nextgis/android_muni_gisconf

Tài liệu SDK: http://docs.nextgis.com/ngmobile_dev/toc.html


1

Có hỗ trợ đầy đủ cho các bản đồ ngoại tuyến với bản phát hành ArcGIS Android SDK hiện tại. Đây mẫu sẽ cho bạn thấy làm thế nào để làm việc với một Tile địa phương Package như một bản đồ cơ sở và duy trì các tính năng trực tuyến để ẩn các tính năng mà từ đó có những cách bạn có thể chỉnh sửa. Tôi có một ý chính có sẵn trên github để tham khảo đơn giản hóa.


1

Tôi khuyên bạn nên xem qua SDK bản đồ 3D của Nutiteq có khả năng ngoại tuyến và các tính năng bổ sung thú vị như hỗ trợ 3D. Nó được tạo ra bởi công ty phát triển chuyên ngành đằng sau nó, vì vậy nó có hỗ trợ thương mại chuyên dụng và linh hoạt hơn các nhà cung cấp lớn cung cấp. Disclaimer: Tôi là nhà phát triển của nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.