Load vector feature data from a GeoPackage


There are several different ways to create and read a GeoPackage. Most of the implementing software products have their own unique way of supporting the handling of a GeoPackage. In this chapter we will show how a GeoPackage can be read using the free and open source GeoPackage Java library that can be found here .

For ease of reference, we reproduce the GeoPackage schema overview below.


The gpkg_spatial_ref_sys table contains coordinate reference system definitions that are used to reference vector and tile data in user tables to locations on the earth.

The gpkg_contents table provides a list of all geospatial contents in a GeoPackage to allow applications to identify and describe geospatial data that is available for access and/or update.

The gpkg_geometry_columns table specifies the type of geometry supported by user data tables containing features.

The gpkg_tile_matrix_set table provides records identifying each tile pyramid user data table contained in the GeoPackage.

The gpkg_tile_matrix table documents the structure of the tile matrix at each zoom level in each tiles table.

The gpkg_extensions table or updateable view in a GeoPackage is used to indicate that a particular extension applies to a GeoPackage, a table in a GeoPackage, or a column of a table in a GeoPackage.

The gpkg_data_columns table stores a minimal description of the schema of feature and tile matrix data tables that supplements the data available from the SQLite sqlite_master table and pragma table_info(table_name) SQL function.

The gpkg_data_column_constraints table contains data to specify restrictions on basic data type column values.

The gpkg_metadata table allows for metadata to be stored inside the GeoPackage.

The gpkg_metadata_reference table relates metadata records stored in the gpkg_metadata to feature and tile data stored in the GeoPackage.

Why does GeoPackage have these tables?

The GeoPackage standard implements the OGC OpenGIS® Simple Features Interface Standard (SFS) which provides a common way for applications to store and access feature data in relational or object-relational databases. The specific tables that play a key role in this are the gpkg_geometry_columns , gpkg_spatial_ref_sys, gpkg_contents and a user-named table that contains the feature properties. Use of the SFS by GeoPackage allows implementations of the GeoPackage standard to make use of the large number of spatial reference systems available from registers such as the EPSG Geodetic Parameter Registry. Use of the SFS by GeoPackage also makes GeoPackages interoperable with other formats that use the SFS, for example the OGC Geography Markup Language (GML). This means that data can be exchanged between a GeoPackage and other SFS-based formats with minimal or no information loss because the data models are based on a common feature model.

The GeoPackage standard adopts a tile-based pyramid structure for storing imagery and raster maps at multiple resolutions. An illustration of this structure is shown below. The specific tables that play a key role in storage of such data include gpkg_tile_matrix_set , gpkg_tile_matrix , gpkg_contents and a user-named table that contains the actual binary encoded tiles. This tile-based pyramid structure is particularly useful when handling a GeoPackage on small or constrained devices such as mobile phones, tablets or laptops because an appropriate resolution can be selected based on the zoom level and the device screen size.


Using the NGA GeoPackage Java library

The open source NGA GeoPackage Java library has been designed to closely abstract the tables of a GeoPackage. The library offers a Data Access Object (DAO) for each of the core tables found in a GeoPackage.

Features and tiles can be accessed from the DAO instances and queried to extract metadata or feature properties. The following code block presents an annotated example of a program that reads two separate GeoPackages, one containing vector features and another containing tiles of imagery. The source code has been adapted from the GeoPackage Java library website . Note that the example uses the states10.gpkg and bluemarble.gpkg sample files. Both files can be downloaded from the Luciad website .

package org.opengeospatial.GeoPackageDemo;

import java.io.File;
import java.util.List;
import mil.nga.geopackage.GeoPackage;
import mil.nga.geopackage.core.contents.ContentsDao;
import mil.nga.geopackage.core.srs.SpatialReferenceSystemDao;
import mil.nga.geopackage.extension.ExtensionsDao;
import mil.nga.geopackage.features.columns.GeometryColumnsDao;
import mil.nga.geopackage.features.user.FeatureDao;
import mil.nga.geopackage.features.user.FeatureResultSet;
import mil.nga.geopackage.features.user.FeatureRow;
import mil.nga.geopackage.geom.GeoPackageGeometryData;
import mil.nga.geopackage.io.GeoPackageTextOutput;
import mil.nga.geopackage.manager.GeoPackageManager;
import mil.nga.geopackage.metadata.MetadataDao;
import mil.nga.geopackage.metadata.reference.MetadataReferenceDao;
import mil.nga.geopackage.schema.columns.DataColumnsDao;
import mil.nga.geopackage.schema.constraints.DataColumnConstraintsDao;
import mil.nga.geopackage.tiles.matrix.TileMatrixDao;
import mil.nga.geopackage.tiles.matrixset.TileMatrixSetDao;
import mil.nga.geopackage.tiles.user.TileDao;
import mil.nga.geopackage.tiles.user.TileResultSet;
import mil.nga.geopackage.tiles.user.TileRow;
import mil.nga.wkb.geom.Geometry;

 * GeoPackage demonstration
public class App {

  * This method reads a GeoPackage file and prints out the contents to the console
  public void read(File geopackageFile) {

          // Open a GeoPackage and create an handle to it
          GeoPackage geoPackage = GeoPackageManager.open(geopackageFile);

          // Create DAO instances of GeoPackage tables
          SpatialReferenceSystemDao srsDao = geoPackage.getSpatialReferenceSystemDao(); //accesses gpkg_spatial_ref_sys
          ContentsDao contentsDao = geoPackage.getContentsDao();   //accesses gpkg_contents
          GeometryColumnsDao geomColumnsDao = geoPackage.getGeometryColumnsDao();  //accesses gpkg_geometry_columns
          TileMatrixSetDao tileMatrixSetDao = geoPackage.getTileMatrixSetDao();  //accesses gpkg_tile_matrix_set
          TileMatrixDao tileMatrixDao = geoPackage.getTileMatrixDao();   //accesses gpkg_tile_matrix
          DataColumnsDao dataColumnsDao = geoPackage.getDataColumnsDao();  //accesses gpkg_data_columns
          DataColumnConstraintsDao dataColumnConstraintsDao = geoPackage.getDataColumnConstraintsDao(); //accesses gpkg_data_columns_constraints
          MetadataDao metadataDao = geoPackage.getMetadataDao(); //accesses gpkg_metadata
          MetadataReferenceDao metadataReferenceDao = geoPackage.getMetadataReferenceDao();  //accesses gpkg_metadata_reference
          ExtensionsDao extensionsDao = geoPackage.getExtensionsDao(); //accesses gpkg_extensions

          // Feature and tile tables
          List<String> features = geoPackage.getFeatureTables();
          List<String> tiles = geoPackage.getTileTables();

          // If there are any features print their properties (as represented by column names and values)
          if (features.size() > 0) {
                  FeatureDao featureDao = geoPackage.getFeatureDao(features.get(0));
                  FeatureResultSet featureResultSet = featureDao.queryForAll();
                  try {
                          while (featureResultSet.moveToNext()) {
                                  FeatureRow featureRow = featureResultSet.getRow();
                                  String[] columnNames = featureRow.getColumnNames();
                                  for(String columnName: columnNames)

                  } finally {


          // If there are any tiles in the GeoPackage, then print out information about the tile tables
          if (tiles.size() > 0) {

                  TileDao tileDao = geoPackage.getTileDao(tiles.get(0));
                  TileResultSet tileResultSet = tileDao.queryForAll();

                  //Now print out descriptions of the tiles
                  StringBuilder output = new StringBuilder();
                  GeoPackageTextOutput textOutput = new GeoPackageTextOutput(

          // Close the database when done


   * This is the main method. It creates an array of two GeoPackage files, one consisting of vector feature data and another consisting of imagery tile data.
  public static void main(String[] args) {

          //Create an array of two GeoPackage files.
          File[] existingGeoPackages = new File[2];
          existingGeoPackages[0] = new File("/Users/Shared/states10.gpkg");
          existingGeoPackages[1] = new File("/Users/Shared/bluemarble.gpkg");

          //Pass each of the files in the array to the read() method for reading
          App app = new App();
          for(File existingGeoPackage: existingGeoPackages){



When the program runs it prints out the feature and tile datasets, including feature properties and tile matrix descriptions.

To run this program, create a Maven project and add the following dependency to the configuration file of the Maven project. This will allow the library dependencies to be pulled in from the Maven Central Repository. A quick start guide for creating a Maven project can be found on the maven website.