I am trying to load OpenStreetMaps on an android app but the map does not load correctly. They are displayed unordered.
I am using a self-hosted map server which loads correctly in a browser (Used leaflet for the demo).
The code as follows,
public class MapActivity extends AppCompatActivity {
final private int MIN_ZOOM_LEVEL = 3;
final private int MAX_ZOOM_LEVEL = 18;
final private int TILE_SIZE = 256;
final private String IMAGE_EXTENSION = ".png";
MapView map = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//load/initialize the osmdroid configuration
Context ctx = getApplicationContext();
Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));
setContentView(R.layout.activity_map);
map = (MapView) findViewById(R.id.map);
map.setTilesScaledToDpi(true);
map.setMultiTouchControls(true);
map.setTileSource(new OnlineTileSourceBase("Tiles", 2, 18, 256, ".png",
new String[] { "http://maps.MY-DOMAIN.com/tile/" }) {
#Override
public String getTileURLString(long pMapTileIndex) {
String url = getBaseUrl()
+ MapTileIndex.getZoom(pMapTileIndex)
+ "/" + MapTileIndex.getX(pMapTileIndex)
+ "/" + MapTileIndex.getY(pMapTileIndex)
+ mImageFilenameEnding;
Log.e("MAP",url);
return url;
}
});
}
}
What I end up getting is,
How can I solve this issue? I have taken a look into the documentation but nothing is mentioned about this.
Either the tile source is z/x/y vs z/y/x OR the y coordinate is inverted the tile source is closer to the TMS specification vs the slippy map format that open street maps uses. In either case, correct the issue, clear the tile cache, then try it again
Related
I am trying to display map tiles using osmdroid. but it is displaying blank screen.
This is my code:
map.setZ(100);
map.setTileSource(new OnlineTileSourceBase("", 12, 18, 256, ".png",
new String[]{"https://storage.googleapis.com/brainpool/user-files/brainpoollicense/maptiles/PL53LY4K0EDYMX/"}) {
#Override
public String getTileURLString(long pMapTileIndex) {
return getBaseUrl()
+ MapTileIndex.getZoom(pMapTileIndex)
+ "/" + MapTileIndex.getX(pMapTileIndex)
+ "/" + MapTileIndex.getY(pMapTileIndex)
+ mImageFilenameEnding;
}
});
map.setMultiTouchControls(true);
IMapController mapController = map.getController();
GeoPoint startPoint;
startPoint = new GeoPoint(151.2927108765, -32.779342448);
mapController.setZoom(12F);
mapController.setCenter(startPoint);
map.invalidate();
createmarker();
This is output:
Also, note that i am getting this in output always:
W/OsmDroid: Problem downloading MapTile: /12/1674/2 HTTP response: Not Found
My question is when getTileURLString method is called? because it is called for the values which are taking wrong z/x/y which do not exist on the server.
I have a WMS tile source overlay on my Osmdroid map.
On the overridden getTileURLString function I add time dimension to get a tile from a specific time.
#Override
public String getTileURLString(long pMapTileIndex) {
//https://stackoverflow.com/questions/28436050/how-to-work-osmdroid-with-web-map-service-wms-used-by-the-private-provider
String baseUrl = getBaseUrl();
StringBuilder sb = new StringBuilder(baseUrl);
if (!baseUrl.endsWith("&"))
sb.append("&");
sb.append("request=GetMap&width=").append(getTileSizePixels()).append("&height=").append(getTileSizePixels()).append("&version=").append("1.3.0");
sb.append("&layers=").append("radar-swiss:radarswiss");
sb.append("&bbox=");
MapView.WebMercatorBoundingBox bb = new MapView.WebMercatorBoundingBox(MapTileIndex.getX(pMapTileIndex), MapTileIndex.getY(pMapTileIndex), MapTileIndex.getZoom(pMapTileIndex));
sb.append(bb.getWest()).append(",");
sb.append(bb.getSouth()).append(",");
sb.append(bb.getEast()).append(",");
sb.append(bb.getNorth());
sb.append("&srs=").append("EPSG:3857");
sb.append("&format=image/png&transparent=true");
sb.append("&tiled=true");
if (currentFrameTiming != null) {
String mDateTime = getDateTimeFromTimeStamp(currentFrameTiming.getTimeInMillis(), WMSTimeFormat);
sb.append("&time=").append(mDateTime);
}
L.d("rewritten url: " + sb.toString());
return sb.toString();
}
Everything works fine but even time parameter seems to be ignored when osmdroid caches tiles. Even if time parameter is modified, the tile is not downloaded, but taken from the local cache.
How can I fix this?
I have an Android application that loads tiles from a URL. Following a code sample from Google, I have the following function:
#Override
public void onMapReady(GoogleMap googleMap) {
mapView = googleMap;
mapView.setMapType(GoogleMap.MAP_TYPE_NORMAL);
LatLng baseLocation = new LatLng(37.745446, -122.459264);
mapView.addMarker(new MarkerOptions().position(baseLocation).title("Marker"));
mapView.moveCamera(CameraUpdateFactory.newLatLng(baseLocation));
mapView.moveCamera(CameraUpdateFactory.zoomTo(5));
TileProvider tileProvider = new UrlTileProvider(256, 256) {
#Override
public synchronized URL getTileUrl(int x, int y, int z) {
String formattedUrl = String.format(Locale.US, TILE_SERVER_URL, x, y, z);
URL url = null;
try {
url = new URL(formattedUrl);
Log.d("TILE_URL", url.toString());
}
catch (MalformedURLException ex) {
throw new AssertionError(ex);
}
return url;
}
};
tiles = mapView.addTileOverlay(new TileOverlayOptions().zIndex(0.0f).tileProvider(tileProvider).visible(true));
}
This has already been implemented in our iOS version and works as expected. Furthermore, I have verified that the URLs returned to the console in this function definitely result in a tile image being returned.
I'm primarily an iOS person and need some insight here. No tiles show up on the map. I've played around with zIndex of the tile overlay with no effect.
Can anyone offer some advice here? Thanks!
I am assuming you followed Google's TileOverlayDemoActivity example: if this is the case, you have to update the URL format protocol from http to https, as follows:
private static final String MOON_MAP_URL_FORMAT =
"https://mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw/%d/%d/%d.jpg";
It took me ages to figure it out, I hope this helps.
I am trying to get the app code and display it, for an example if button X starts a new activity then a textView displays the whole method
I reached only how can I display code in HTML format from this question
But is there is a way to get the code of my app out, I think that there are 2 ways
An Internal one by getting it by the app itself
An External one by reading the java file then filtering it and getting the text of the method
Is there are any ideas about that?
Thanks in advance
The above is not currently possible as mentioned by others is the comments. What i can suggest is shipping your application with the source code in the assets folder and using a helper function to extract a certain methods from the source at runtime (your second proposed approach). I have written example code but it is in pure java and needs to be ported to android (a few lines).
NB: You may need to reformat the code after extraction depending on your use case.
Hope it helps :)
The code for the helper method:
static String getTheCode(String classname ,String methodSignature ) throws FileNotFoundException {
//**********************A few lines of code below need changing when porting ***********//
// open file, your will be in the assets folder not in the home dir of user, don't forget the .java extension when porting
File file = new File(System.getProperty("user.home") +"/"+ classname +".java");
// get the source, you can use FileInputReader or some reader supported by android
Scanner scanner = new Scanner(file);
String source = "";
while(scanner.hasNext()) {
source += " "+ scanner.next();
}
//**********************The above code needs changing when porting **********//
// extract code using the method signature
methodSignature = methodSignature.trim();
source = source.trim();
//appending { to differentiate from argument as it can be matched also if in the same file
methodSignature = methodSignature+"{";
//making sure we find what we are looking for
methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "(");
methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")");
methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ",");
methodSignature = methodSignature.replaceAll("\\s+", " ");
source =source.replaceAll("\\s*[(]\\s*", "(");
source = source.replaceAll("\\s*[)]\\s*", ")");
source = source.replaceAll("\\s*[,]\\s*", ",");
source = source.replaceAll("\\s+", " ");
if(!source.contains(methodSignature)) return null;
// trimming all text b4 method signature
source = source.substring(source.indexOf(methodSignature));
//getting last index, a methods ends when there are matching pairs of these {}
int lastIndex = 0;
int rightBraceCount = 0;
int leftBraceCount = 0;
char [] remainingSource = source.toCharArray();
for (int i = 0; i < remainingSource.length ; i++
) {
if(remainingSource[i] == '}'){
rightBraceCount++;
if(rightBraceCount == leftBraceCount){
lastIndex = (i + 1);
break;
}
}else if(remainingSource[i] == '{'){
leftBraceCount++;
}
}
return source.substring(0 ,lastIndex);
}
Example usage (getTheCode methods is static and in a class called GetTheCode):
public static void main(String... s) throws FileNotFoundException {
System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut()"));
System.out.println(GetTheCode.getTheCode("Main", "private static void shoutOut(String word)"));
}
Output:
private static void shoutOut(){ // nothing to here }
private static void shoutOut(String word){ // nothing to here }
NB: When starting your new activity create a method eg
private void myStartActivty(){
Intent intent = new Intent(MyActivity.this, AnotherActivity.class);
startActivity(intent);
}
Then in your onClick:
#Override
public void onClick(View v) {
myStartActivity();
myTextView.setText(GetTheCode.getTheCode("MyActivity","private void myStartActivity()"));
}
Update: Ported the Code for android:
import android.content.Context;
import java.io.IOException;
import java.util.Scanner;
public class GetTheCode {
static String getTheCode(Context context, String classname , String methodSignature ) {
Scanner scanner = null;
String source = "";
try {
scanner = new Scanner(context.getAssets().open(classname+".java"));
while(scanner.hasNext()) {
source += " "+ scanner.next();
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
scanner.close();
// extract code using the method signature
methodSignature = methodSignature.trim();
source = source.trim();
//appending { to differentiate from argument as it can be matched also if in the same file
methodSignature = methodSignature+"{";
//making sure we find what we are looking for
methodSignature = methodSignature.replaceAll("\\s*[(]\\s*", "(");
methodSignature = methodSignature.replaceAll("\\s*[)]\\s*", ")");
methodSignature = methodSignature.replaceAll("\\s*[,]\\s*", ",");
methodSignature = methodSignature.replaceAll("\\s+", " ");
source =source.replaceAll("\\s*[(]\\s*", "(");
source = source.replaceAll("\\s*[)]\\s*", ")");
source = source.replaceAll("\\s*[,]\\s*", ",");
source = source.replaceAll("\\s+", " ");
if(!source.contains(methodSignature)) return null;
// trimming all text b4 method signature
source = source.substring(source.indexOf(methodSignature));
//getting last index, a methods ends when there are matching pairs of these {}
int lastIndex = 0;
int rightBraceCount = 0;
int leftBraceCount = 0;
char [] remainingSource = source.toCharArray();
for (int i = 0; i < remainingSource.length ; i++
) {
if(remainingSource[i] == '}'){
rightBraceCount++;
if(rightBraceCount == leftBraceCount){
lastIndex = (i + 1);
break;
}
}else if(remainingSource[i] == '{'){
leftBraceCount++;
}
}
return source.substring(0,lastIndex);
}
}
Usage:
// the method now takes in context as the first parameter, the line below was in an Activity
Log.d("tag",GetTheCode.getTheCode(this,"MapsActivity","protected void onCreate(Bundle savedInstanceState)"));
Let's start with a broader overview of the problem:
Display App code
Press X button
Open new activity with a textview which displays the method
The goal is to do the following:
Viewing app method by extracting it and then building & running it.
There are some methods we can use to run Java/Android code dynamically. The way I would personally do it is DexClassLoader and with Reflection.
If you need more details, let me know. Here is what it'd do though:
View app method
Upon pressing X, launch intent with extra to new Activity
Parse and compile code dynamically and then run it with DexClassLoader and Reflection
Sources:
Sample file loading Java method from TerminalIDE Android App
Android Library I made for Auto-Updating Android Applications without needing the Play Store on non-root devices
I have integrated sygic in my android application using a surface view. I want to navigate in that sygic application . I have used this code :
SWayPoint wp = new SWayPoint();
wp.Location = new LONGPOSITION(34, 35);
ApplicationAPI.StartNavigation(err, wp, 0, true, false, MAX);
But it is not working. Any ideas ?
I have once implemented Sygic in an app and this is basically how my code looks like (after hours of debug because the documentation was very poor...):
// surfaceView for displaying the "map"
SurfaceView mSygicSurface = (SurfaceView) findViewById(R.id.sygic_surface); // surface
// api status
int mSygicAPIStatus = -2;
// start the drive
ApplicationAPI.startDrive(new ApiCallback() {
public void onRunDrive() {
mSygicSurface.post(new Runnable() {
public void run() {
runDrive(mSygicSurface, getPackageName());
}
});
}
public void onInitApi() // gets called after runDrive();
{
mSygicAPIStatus = ApplicationAPI.InitApi(getPackageName(), true, new ApplicationHandler() { /* nothing relevant here */ }); // api initialization
if (mSygicAPIStatus != 1) {
// error
return;
}
}
});
Once you want to navigate somewhere:
GeoPoint point = new GeoPoint(/* ... */, /* ... */);
final SWayPoint wayPoint = new SWayPoint("", point.getLongitudeE6(), point.getLatitudeE6());
SError error = new SError();
final int returnCode = ApplicationAPI.StartNavigation(error, point, NavigationParams.NpMessageAvoidTollRoadsUnable, true, true, 0);
Carefully note that Sygic uses E6 coordinates.
This is not an answer on the question, but for whose who searching for weird sygic exmaples in 2017 I put it here
ApiMaps.showCoordinatesOnMap(new Position((int)(-84.41949*100000.0),(int)(33.7455*100000.0)),1000,0);
//LONGITUDE first!!
//and multiply on 100 000
//https://developers.sygic.com/reference/java3d/html/classcom_1_1sygic_1_1sdk_1_1remoteapi_1_1_api_maps.html
p.s. this is for standalone apk