android mapview custom tile - android

I need to add a custom base layer to to my map view. My understanding is that the map tiles are exactly the same as the google tiles. They are static files served up in the following format: http:///tilecache///.png
For example, the http:///tilecache/6/16/26.png is the gulf coast between florida alabama and mississippi.
How do I create an overlay with the tiles?

osmdroid (as recommended above) is cool but quite huge. Some time ago I decided to use http://sourceforge.net/projects/libwlocate/ instead - it contains functionalities for showing/scrolling/zooming maps like osmdroid but you can choose to use OSM, Google Maps or Google satellite view.
An example how to use it can be found in http://libwlocate.git.sourceforge.net/git/gitweb.cgi?p=libwlocate/libwlocate;a=blob;f=master/android/LocDemo/src/com/vwp/locdemo/LocDemo.java;h=5e2134fb7d197258f5f4f6f9021d2fa9ad9f2d9a;hb=HEAD

I would recommend using osmdroid. You can extend OnlineTileSourecBase.
public class YourTileSource extends OnlineTileSourceBase implements IStyledTileSource<Integer> {
public YourTileSource (String aName, string aResourceId,
int aZoomMinLevel, int aZoomMaxLevel, int aTileSizePixels,
String aImageFilenameEnding, String aBaseUrl) {
super(aName, aResourceId, aZoomMinLevel, aZoomMaxLevel, aTileSizePixels,
aImageFilenameEnding, aBaseUrl);
}
public void setStyle(Integer style) {
// TODO Auto-generated method stub
}
public void setStyle(String style) {
// TODO Auto-generated method stub
}
public Integer getStyle() {
// TODO Auto-generated method stub
return null;
}
#Override
public String getTileURLString(MapTile aTile) {
return getBaseUrl() + "/" + aTile.getX() + "/" + aTile.getY() + "/" + aTile.getZoomLevel() + ".png";
}
}
Then add your tile source to your mapview:
TileSourceFactory.addTileSource(new YourTileSource ("YourTileSource", null, 1, 20, 256, ".png", "http:///tilecache/"));
mapView.setTileSource(TileSourceFactory.getTileSource("YourTileSource"));
Your mapView needs to be an org.osmdroid.views.MapView for that to work. OSMdroid classes should replace all of the google maps classes.
Start by downloading the osmdroid-android-3.0.8.jar file, add it to your libs folder in your project, and then add it to the project through right click > Properties > Java Build Path > Libraries > Add Jars, and then find it in the libs folder. Post more questions if you have them, I have a lot of experience with osmdroid.

For newer versions of OSMDroid, the aResourceId parameter to the constructor has been removed and the last parameter, aBaseUrl, is a String[]
public YourTileSource (String aName,
int aZoomMinLevel,
int aZoomMaxLevel,
int aTileSizePixels,
String aImageFilenameEnding,
String[] aBaseUrl) {
super(aName,
aZoomMinLevel,
aZoomMaxLevel,
aTileSizePixels,
aImageFilenameEnding,
aBaseUrl);
}

Related

Purpose of the `aBaseUrl` parameter in the class OnlineTileSourceBase?

I don't understand the purpose of the aBaseUrl parameter in the class OnlineTileSourceBase. My reason for inquiring is that I am trying to get offline tiles to display and thus far can't get it to work. I see the overlay I created, but no map data (just that grey grid) and I wonder if I need to set aBaseUrl to something appropriate.
The data is on the device is in sdcard/osmdroid/tiles/Mapnik/.
Mapnik contains folders 0, 1, ... 14, which themselves contains folders which contain .jpg files.
Online, this code works (removing the call setUseDataConnection(false) and setting tile source to MAPNIK). Based on code by #nightfixed here.
public class MapActivity extends AppCompatActivity {
final private int MIN_ZOOM_LEVEL = 0;
final private int MAX_ZOOM_LEVEL = 14;
final private int TILE_SIZE = 256;
final private String IMAGE_EXTENSION = ".jpg";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
CustomTileSource tileSource = new CustomTileSource ("Default",
MIN_ZOOM_LEVEL,
MAX_ZOOM_LEVEL,
TILE_SIZE,
IMAGE_EXTENSION,
CustomTileSource.TILE_URL);
final MapView mapView = (MapView) findViewById(R.id.mapview);
mapView.setTileSource(tileSource);
// mapView.setTileSource(TileSourceFactory.MAPNIK);
mapView.setUseDataConnection(false); // keeps the mapView from loading online tiles using network connection.
}
}
public class CustomTileSource extends OnlineTileSourceBase {
public static String[] TILE_URL = {"my_url"};
public CustomTileSource (String aName,
int aZoomMinLevel,
int aZoomMaxLevel,
int aTileSizePixels,
String aImageFilenameEnding,
String[] urlArray) {
super(
aName,
aZoomMinLevel,
aZoomMaxLevel,
aTileSizePixels,
aImageFilenameEnding,
urlArray);
}
// returns the url for each tile, depending on zoom level
// this is where I changed the return statement to take the first url from the string array of urls
#Override
public String getTileURLString(MapTile aTile) {
return TILE_URL[0] + aTile.getX() + "+" + aTile.getY() + "+" + aTile.getZoomLevel();
}
}
I suggest you to follow closely this post: Download maps for osmdroid
No need for CustomTileSource, just use mapView.setTileSource(TileSourceFactory.MAPNIK);
If your tiles are in "Mapnik" dir (sdcard/osmdroid/tiles/Mapnik) then TileSource aName should be set to "Mapnik", not to "Default".
When offline, aBaseUrl doesn't matter.
aBaseUrl is basically the primary url to the online map server. For example
http://tiles.mymapserver.com/mapdata (note, complete fictitious)
After the aBaseUrl, osmdroid calculates with tiles to load via various algorithms and then appends something like /Z/X/Y.jpg to the end of the aBaseUrl string when downloading.

android multiple themes, one app

I need to develop an app, which can for some users (defined by server) set different app colors.
I have read a lot of custom theme with usage of attr.xml file, but android studio builder will be broken if I would use it.
So i have developed another approach - I subclassed Resorses class of my BaseActivity:
CustomResource customResource;
#Override
public Resources getResources() {
if (customResource == null) {
customResource = new CustomResource(super.getAssets(), super.getResources().getDisplayMetrics(), super
.getResources().getConfiguration());
}
return customResource;
}
public class CustomResource extends Resources {
public CustomResource(AssetManager assets, DisplayMetrics metrics, Configuration config) {
super(assets, metrics, config);
}
#Override
public int getColor(int id) throws NotFoundException {
Log.d("TAG", "id: " + id + " getResourceName: " + getResourceName(id));
Log.i("TAG", "Came Color: "+super.getColor(id));
return getColor ( getResourceName(id) , id);
}
public int getColor(String aString, int oldId) {
String packageName = getPackageName();
int resId = getIdentifier(getThemeColorName(aString),null,null);
Log.v("TAG", "resId: "+resId);
if (resId != 0) {
Log.i("TAG", "We SET Color: "+super.getColor(resId));
return super.getColor(resId);
} else {
return super.getColor(oldId);
}
}
private String getThemeColorName(String aString){
int pos = aString.lastIndexOf('/');
if (pos != -1){
aString = aString.substring(0, pos+1) + "b" + aString.substring(pos+1, aString.length());
}
Log.d("TAG", "aString NOW: " + aString);
return aString;
}
}
And retreive appropriet resource (just for testing, I am pulling out instead of "someColor" -> "bsomeColor".
As I look into log, everything is working, colors are being changing.
But if I set colors from xml (activities layout) I see all methods are being exected (sucessfully), but on my screen android epplyies colors without "b" prefix (BUT all my methods are being called - getColor() for every view, and I return super.getColor for an appropriate color, what I need!
Please, give me ideas how this can be solved, or give me other options to nicely introduce multiple themes, not breaking the xml editor

Is it a good thing to write logic based on the hex value of id generated in R.java android

This what I have seen in an android application. They have a number of image buttons with ids
R.java :
public static final int img1=0x7f090080;
public static final int img2=0x7f090081;
public static final int img3=0x7f090082;
public static final int img4=0x7f090083;
public static final int img5=0x7f090084;
public static final int img6=0x7f090085;
public static final int img7=0x7f090086;
public static final int img8=0x7f090087;
In one of the activity they are traversing a for loop like below:
for (int i = 0; i < NoOfButtons; i++) {
if (i == pos) {
((ImageView) vi.findViewById(R.id.img1 + i)).setImageResource(R.drawable.circular_pagination_red);
} else {
((ImageView) vi.findViewById(R.id.img1 + i)).setImageResource(R.drawable.circular_pagination_brown);
}
I want to know how much safe and advisable it is.
One thing this is working absolutely fine. I been a part of this from months and never seen a problem in this logic. But still it irks me a bit.
Note : I am not getting any error and I know the alternate solution also. My only concern is if it is not advisable/safe I want to know why? Another is scenarios where it can create havoc for me. I have a good understanding about R.java.
Though this might work OK most of the times, this is definitely not advisable. The R class is generated automatically thus you have no control over it and it could change. There is a solution to this problem using a typed array in resources. Check for example this answer.
You might want to use reflection.
Add this method to your code:
protected final static int getResourceID
(final String resName, final String resType, final Context ctx)
{
final int ResourceID =
ctx.getResources().getIdentifier(resName, resType,
ctx.getApplicationInfo().packageName);
if (ResourceID == 0)
{
throw new IllegalArgumentException
(
"No resource string found with name " + resName
);
}
else
{
return ResourceID;
}
}
And use it like this:
int myID =
getResourceID("your_resource_name", "drawable", getApplicationContext());
Note: no path (and no extension, in case of images).

setTag() on button click for multiple value

dater.setText(theday);
dater.setTag(1, theday);
dater.setTag(2, theday + "-" + themonth + "-" + theyear);
dater.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
notification(date_txt);
String day = v.getTag(1).toString();
date_txt.setText(day);
}
});
im doing set tag for a textview im doing it using settag(int key object tag); and settag(key) but im getting error which i cant figure out any ideas on this thank you
dater.setText(theday);
List<String> data = new ArrayList<String>();
data.add(theday);
data.add(theday + "-" + themonth + "-" + theyear);
dater.setTag(data);
dater.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
notification(date_txt);
ViewHold holder=v.getTag
String day = ((List<String>)v.getTag()).get(1).toString();
date_txt.setText(day);
}
});
this answer in very usefull
textView.setTag(new HoldsTwoObjs(obj1, obj2));
HoldsTwoObjs isTagClass=(HoldsTwoObjs)textView.getTag();
https://stackoverflow.com/a/27528427/1140304
The key that you use in settag(int key object tag); should be an id declared in your resources.
According to the documentation
Sets a tag associated with this view and a key. A tag can be used to mark a view in its
hierarchy and does not have to be unique within the hierarchy. Tags can also be used to
store data within a view without resorting to another data structure. **The specified key
should be an id declared in the resources of the application to ensure it is unique (see
the ID resource type). Keys identified as belonging to the Android framework or not
associated with any package will cause an IllegalArgumentException to be thrown.**

How to create osmdroid XYTileSource for offline tiles in version 4.1?

I have offline osmdroid maps working using version 4.0. Upgrading to 4.1, they no longer work. I have narrowed the problem down to the XYTileSource, in which aBaseUrl changed from being a string in 4.0 to and array in 4.1. How do I get offline tiles to work in 4.1?
Old 4.0 code that worked. The tiles are in /sdcard/osmdroid/tiles.zip
XYTileSource ts = new XYTileSource ( "tiles",
ResourceProxy.string.offline_mode,
13,
17,
256,
".png",
"http://127.0.0.1");
mapView = (MapView) findViewById(R.id.mapview);
mapView.setTileSource(ts);
mapView.setMultiTouchControls(true);
mapView.setBuiltInZoomControls(false);
mapView.setUseDataConnection(false);
mapView.getController().setZoom(15);
GeoPoint point = new GeoPoint(40.715,-73.945);
mapView.getController().setCenter(point);
I tried changing it to this, but it doesn't work.
String[] urls = {"http://127.0.0.1"};
XYTileSource ts = new XYTileSource ( "tiles",
ResourceProxy.string.offline_mode,
13,
17,
256,
".png",
urls);
I tried to provide a full answer here:
Download maps for osmdroid
If you have an "old" tiles.zip, open it, and check:
the root directory name => put it as the "aName" of XYTileSource constructor (is it really "tiles"?)
the tiles images extension => put it as the aImageFileNameEnding (is it really ".png"?)
The aResourceId and aBaseUrl params are not used for zip files.
I see that you are using XYTileSource, which by default extends OnlineTileSourceBase.
I have found a workaround for the Url issue, by creating a CustomTileSource class. Something like below:
public class CustomTileSource extends OnlineTileSourceBase {
public static String[] TILE_URL = {"my_url"};
//constructor is default - I changed nothing here
public CustomTileSource (String aName, string aResourceId, int aZoomMinLevel, int aZoomMaxLevel,
int aTileSizePixels, String aImageFilenameEnding, String[] url) {
super(
aName,
aResourceId,
aZoomMinLevel,
aZoomMaxLevel,
aTileSizePixels,
aImageFilenameEnding,
url);
// TODO Auto-generated constructor stub
}
/**
* returns the url for each tile, depending on zoom level
*/
//this is where I changed the return statement to take the first url from the string array of urls
#Override
public String getTileURLString(MapTile aTile) {
return TILE_URL[0] + aTile.getX() + "+" + aTile.getY() + "+" + aTile.getZoomLevel();
}
}
In my code, where I need to instantiate the tilesource, I use:
CustomTileSource tileSource = new CustomTileSource ("Default", ResourceProxy.string.offline_mode, MIN_ZOOM_LVL, MAX_ZOOM_LVL, DEFAULT_TILE_SIZE, TILE_FORMAT, CustomTileSource.TILE_URL);
//MIN_ZOOM_LVL, MAX_ZOOM_LVL, DEFAULT_TILE_SIZE, TILE_FORMAT are constants that I defined elsewhere
Hope it helps.

Categories

Resources