Hilft es dir, wenn ich dir sage, dass es mit relativ wenig Aufwand möglich ist, einen Tile-Provider für die Google Maps API v2 zu schreiben (soweit ich gelesen habe, ist OSM wohl etwas "frickelig" zu integrieren). Nachteil der Variante wäre allerdings, dass du das Laden der Tiles sowie Caching selbst machen musst, auch ist die Zoomstufe dann nicht so gut (muss man bedenken und ein entsprechendes "no-such-tile"-png oder so liefern) und auch die Qualität ist vielleicht nicht so gut, wie die von OSM selbst...
Allerdings war der Aufwand bei mir mit ca. 8h (inkl. aller notwendiger Recherchen) jetzt auch jetzt nicht soooo schlimm - finde ich.
Wenn du interessiert bist, poste ich mal etwas Code; wenn nicht, dann eben nicht :-D
#edit: und mit Code-Schnipseln wahrscheinlich sogar noch geringer ;-)
Danke dann werd ich wohl auf Google Maps zurückgreifen müssen. Hab ich aber auch schonmal gemacht, wenn auch nur extern also durch öffnen der Maps App. Wenn du Maps richtig in deine App implementiert hast würd ich mich sehr über einen Code-Post freuen :toll:
Wie du Google Maps in deine App integrierst, musst du im Internet suchen - da gibt es schon viele gute Beschreibungen. Du musst hierzu allerdings bei Google einen Key für deine App erstellen - Da kommst du nicht drum herumWenn du bei Google nach google maps api v2 android suchst, solltest du fündig werden - wie fast immer ist auch Tutorial von Lars Vogel mit am Start.
Zusammenfassend wären deine ersten Schritte:
Google Play Services im SDK installieren
diese als lib-Projekt in dein Eclipse importieren
via File > Import > Android > Existing Android Code Into Workspace
dann wähle <Android-SDK-Verzeichnis>/extras/google/google_play_services/libproject
importiere google-play-services_lib (Hacken vorne ran und Ok)
diese lib deinem Projekt hinzufügen
Properties deines Projekts öffnen, Android
unten in der Gruppe Library dann Add... drücken und das lib-Projekt auswählen
Manifest deines Projekts öffnen und nun Permissions u.s.w. hinzufügen
Code:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="ch.cnlab.speedtest.permission.MAPS_RECEIVE" />
<permission
android:name="ch.cnlab.speedtest.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<application
[... deine Einstellungen zur App]>
<uses-library android:name="com.google.android.maps" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="@string/keystore.map.debug" /> <!-- dein Key kann direkt hier drin stehen, ich hab ihn aber in der allg. strings.xml -->
</application>
WRITE_EXTERNAL_STORAGE wegen dem Caching der OSM-Tiles
Ich gehe jetzt davon aus, dass du dir bereits einen Key für deine App bei Google angelegt hast (der Package Name ist hier für Google entscheidend).
Jetzt ist der grösste Aufwand schon getan.
Lege dir jetzt ein layout für deine Map an - ich habe das in einem Layout gemacht, dass ich dann als Fragment in einem Tab-Container eingebunden habe:
Im Fragment geht es dann weiter. Ich musste hier etwas tricksen, da ich in dem Tab-Container ein paar Probleme mit der Map hatte. Verwende folgenden Code, solltest du auch Probleme mit der Map haben, denn diese herangehensweise ist nicht unbedingt die sauberste!
Java:
publicclassMapFragmentextendsFragment{protectedView mView;@OverridepublicViewonCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){// hack!!!if((mView !=null)&&(mView.getParent()!=null)){((ViewGroup) mView.getParent()).removeView(mView);}if(mView ==null){
mView = inflater.inflate(R.layout.fragment_map, container,false);}// das ist dann wieder ok :-)setUpMapIfNeeded();}protectedvoidsetUpMapIfNeeded(){FragmentManager fm =getFragmentManager();Fragment frag = fm.findFragmentById(R.id.fragment_mapview);if(frag ==null){if((mView !=null)&&(mView.getParent()!=null)){((ViewGroup) mView.getParent()).removeView(mView);
mView =null;}return;}else{if(mMap ==null){
mMap =((com.google.android.gms.maps.SupportMapFragment) frag).getMap();}}if(mMap !=null){
mMap.setMyLocationEnabled(true);// die listener musst du jetzt bei Bedarf selbst machen// mMap.setOnCameraChangeListener(mOnCameraChangeListener);// mMap.setOnMapClickListener(mOnMapClickListener);// mMap.setOnMarkerClickListener(mOnMarkerClickListener);// mMap.setInfoWindowAdapter(new MyInfoWindowAdapter(getActivity()));// mMap.setOnInfoWindowClickListener(mOnInfoWindowClickListener);// ich erstelle meine Marker für die Map in einem AsyncTask,damit das UI nicht blockiert// if ((mInitTask != null) && !mInitTask.isCancelled()) {// mInitTask.cancel(true);// }// mInitTask = new MarkerBuilderTask();// mInitTask.execute();}}
für dein Map-Set-Up empfehle ich dir, deine letzten Map-Optionen vielleicht im savedInstanceState zu speichern, oder alternativ eine Präferenz dafür anzulegen (falls du das jetzt noch nicht kennst: Google! ).
Jetzt geht es ans eingemachte: Um den Typ der Map auszutauschen, musst du dir ein Menü, einen Dialog, oder was auch immer, bauen, um via mMap.setMapType(newType); hier umzuschalten.
Ich gehe da grob etwa folgendermaßen vor:
Java:
// der Code hier ist mehr oder weniger Teil des Set-Up!!!if(rgMapOptionView !=null){int type =PreferenceHelper.getMapOptionType(getActivity());if(mCustomTileOverlay !=null){
mCustomTileOverlayOptions =null;
mCustomTileOverlay.remove();
mCustomTileOverlay =null;}if(mMap !=null){switch(type){// Google-TypescaseGoogleMap.MAP_TYPE_NORMAL:
mMap.setMapType(type);
rgMapOptionView.check(R.id.map_option_view_def);break;caseGoogleMap.MAP_TYPE_HYBRID:
mMap.setMapType(type);
rgMapOptionView.check(R.id.map_option_view_sat);break;caseGoogleMap.MAP_TYPE_TERRAIN:
mMap.setMapType(type);
rgMapOptionView.check(R.id.map_option_view_top);break;// Custom - alsoo von mircaseCustomMapType.MAP_TYPE_OSM:// hier kann auch ein weniger bescheuertes Konstrukt verwendent werden! :-DTileProvider osmTileProvider =CustomMapType.CustomTileProviderEnum.OSM.createTileProvider(getActivity());
mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
mCustomTileOverlayOptions =newTileOverlayOptions().tileProvider(osmTileProvider).zIndex(0);
mCustomTileOverlay = mMap.addTileOverlay(mCustomTileOverlayOptions);
mCustomTileOverlay.clearTileCache();
mMap.moveCamera(CameraUpdateFactory.newLatLng(newLatLng(46.954012,8.415527)));
rgMapOptionView.check(R.id.map_option_view_osm);break;// Fallbackdefault:
type =GoogleMap.MAP_TYPE_NORMAL;
mMap.setMapType(type);
rgMapOptionView.check(R.id.map_option_view_def);break;}}
rgMapOptionView.setOnCheckedChangeListener(newRadioGroup.OnCheckedChangeListener(){@OverridepublicvoidonCheckedChanged(RadioGroup group,int checkedId){if(mMap ==null)return;if(mCustomTileOverlay !=null){
mCustomTileOverlayOptions =null;
mCustomTileOverlay.remove();
mCustomTileOverlay =null;}switch(checkedId){caseR.id.map_option_view_def:
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);PreferenceHelper.setMapOptionType(getActivity(),GoogleMap.MAP_TYPE_NORMAL);break;caseR.id.map_option_view_sat:
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);PreferenceHelper.setMapOptionType(getActivity(),GoogleMap.MAP_TYPE_HYBRID);break;caseR.id.map_option_view_top:
mMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);PreferenceHelper.setMapOptionType(getActivity(),GoogleMap.MAP_TYPE_TERRAIN);break;caseR.id.map_option_view_osm:TileProvider osmTileProvider =CustomMapType.CustomTileProviderEnum.OSM.createTileProvider(getActivity());if(osmTileProvider !=null){
mMap.setMapType(GoogleMap.MAP_TYPE_NONE);
mCustomTileOverlayOptions =newTileOverlayOptions().tileProvider(osmTileProvider).zIndex(0);
mCustomTileOverlay = mMap.addTileOverlay(mCustomTileOverlayOptions);PreferenceHelper.setMapOptionType(getActivity(),CustomMapType.MAP_TYPE_OSM);break;}// otherwise we use the fall-through and create the default mapdefault:
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);PreferenceHelper.setMapOptionType(getActivity(),GoogleMap.MAP_TYPE_NORMAL);break;}}});}
Um es halbwegs elegant ( -.- ) zu lösen, habe ich hier übrigens ein Frame-Layout verwendet, das über der Map liegt und mittels Toggle-Button angezeigt, oder ausgeblendet wird.
So. Nun der TileProvider, der die eigentliche Arbeit macht. Im Code war bereits CustomMapType zu sehen: Ein häßliches Ding!
OK, das ist jetzt ein ganzer Batzen! Ich empfehle dir jetzt, erst einmal die ersten Schritte bis zur Integration in deine App durchzuführen und den OSM-Teil erst einmal auszusparen. Ich schätze einen Tag Arbeit wirst du da bereits haben. Aber glaube mir: danach geht es eigentlich sehr schnell. Ich habe schnell ohne großen Aufwand Marker, Polylines (Pfade) und Kreise auf die Map gezimmert, ohne dass es mich dann noch unendlich viel Arbeit gekostet hätte. Das wichtigste ist dann nur es in AsyncTasks auszulagern und dass diese natürlich auch zügig sind - hierzu habe ich viele der notwendigen DB-Operationen (da ich mitunter Joins etc. benötige) zu Plain-SQL umgeschrieben. Aber das war nur in meinen Tests notwendig, in denen ich weit mehr Daten in der App habe, als Otto-Normal-Verbraucher es wohl je haben wird...
Viel Erfolg beim Umsetzen!
Daniel
PS: Wenn du das Ganze mal in Aktion sehen willst, damit du eine Idee hast, was hier passiert, suche im Play Store einmal nach cnlab SpeedTest. Die App ist sicher nicht perfekt, aber alle hier gezeigten Schnipsel sind aus Tutorials, Blogs und Stackoverflow-Beiträgen erstellt, also auch kein Geheimnis - ich war, bevor ich die komplette UI dieser App (neu-)geschrieben hab, übrigens völlig unwissend, wie man Android programmiert, es ist also mit etwas Fleiß machbar!
PPS: Wenn ich von der App rede, meine ich Version 2.3.2, die leider nur auf Geräten mit Android 4+ zur Verfügung steht. Ältere Geräte erhalten die alte Version 1.4.2, die viele Features, wie z.B. die OSM-Integration, nicht besitzt!