i am trying to scale pictures in a Android map itemizedOverlay,
i got it working to the point where i can see 10 pictures, i got zoomControle but nothing else really,
this is the MapItems class that extends ItemizedOverlay, optimizations is welcome
import java.util.ArrayList;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.Log;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
public class MapItems extends ItemizedOverlay
{
private ArrayList<OverlayItem> mOverlays = new ArrayList<OverlayItem>();
Context mContext;
public MapItems(Drawable defaultMarker)
{
super(boundCenterBottom(defaultMarker));
}
#Override
public void draw(android.graphics.Canvas canvas,MapView mapView,boolean shadow)
{
/*
Log.d("MapAc", String.valueOf(mapView.getZoomLevel()));
if(mapView.getZoomLevel() > 20)
{
Log.d("MapAc", "scaling up");
canvas.scale(1.2f, 1.2f);
}
*/
super.draw(canvas,mapView,false);
}
public MapItems(Context context)
{
super(boundCenterBottom(context.getResources().getDrawable(R.drawable.app_icon_clean)));
mContext = context;
}
public void addOverlay(OverlayItem overlay)
{
mOverlays.add(overlay);
populate();
}
public void clearOverlay()
{
mOverlays.clear();
}
#Override
protected OverlayItem createItem(int i)
{
return mOverlays.get(i);
}
#Override
public int size()
{
return mOverlays.size();
}
#Override
protected boolean onTap(int index)
{
/* ToDo
OverlayItem item = mOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
*/
return true;
}
}
i have been trying to scale in the draw method, using canvas.Scale, however this seems to redraw the canvas in another location, together with the old canvas"in its original size",
i am not sure if i am approaching this problem from the right angle, or if it is simply a matter of clearing the screen, i have been using a few days to figure this out, so a method to scale my pictures correct when zooming is VERY appreciated,
Use the new MAPS API V2
Blog article
Video
Related
I am building a audio player i have completed all the Songs browsing (UI) activities and to handle audio playback i am using google sample audio player this and i read all the src from this sample and there is class MusicLibrary in sample code and it contains a sample list of songs like below
public class MusicLibrary {
private static final TreeMap<String, MediaMetadataCompat> music = new TreeMap<>();
private static final HashMap<String, Integer> albumRes = new HashMap<>();
private static final HashMap<String, String> musicFileName = new HashMap<>();
static {
createMediaMetadataCompat(
"Jazz_In_Paris",
"Jazz in Paris",
"Media Right Productions",
"Jazz & Blues",
"Jazz",
103,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/2537.mp3",
R.drawable.album_jazz_blues,
"https://upload.wikimedia.org/wikipedia/en/a/ac/Audioslave_-_Audioslave.jpg");
createMediaMetadataCompat(
"The_Coldest_Shoulder",
"The Coldest Shoulder",
"The 126ers",
"Youtube Audio Library Rock 2",
"Rock",
160,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/4201.mp3",
R.drawable.album_youtube_audio_library_rock_2,
"https://theflagcompany.in/wp-content/uploads/2018/10/Indian-National-Flag-300x300.jpeg");
}
but i am unable to find a method which shows how to add a song in current playlist from other activities for example in my current app there is search activity where user can search any song from internet and i want to add track from this search activity by two different ways 1. add and play song 2. only add song in the end of playlist.
Sample code track object use album art image from drawable folder but in my app i need to show album art from internet (Last FM API) not from local folder i tried to edit MusicLibrary class and created a bitmap from URI unable to make it work so this is alos i need to modify in sample code.
Sample code contains only on simple activity where when you open it opens a audio player interface but in my app in HomeActivity there are some fragments and a mini player at bottom now like below
Please help me with these two things
add songs to player from my code
use internet image for METADATA_KEY_ALBUM_ART
i just want to merge these two things and i am new to android so no luck please guide me so that i can complete my project. Thanks in advance :)
My Main Activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//add song in sample player service from this method
public void addSongQue(Song song) {
title = song.getTile;
artist = song.getArtist;
mp3Url = song.getSrc;
albumArtImage = song.getAlbumArt;
.......
...
}
}
Sample Code Player Activity full sample src is here
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.mediasession.R;
import com.example.android.mediasession.client.MediaBrowserHelper;
import com.example.android.mediasession.service.MusicService;
import com.example.android.mediasession.service.contentcatalogs.MusicLibrary;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ImageView mAlbumArt;
private TextView mTitleTextView;
private TextView mArtistTextView;
private ImageView mMediaControlsImage;
private MediaSeekBar mSeekBarAudio;
private MediaBrowserHelper mMediaBrowserHelper;
private boolean mIsPlaying;
//https://github.com/googlesamples/android-MediaBrowserService
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitleTextView = findViewById(R.id.song_title);
mArtistTextView = findViewById(R.id.song_artist);
mAlbumArt = findViewById(R.id.album_art);
mMediaControlsImage = findViewById(R.id.media_controls);
mSeekBarAudio = findViewById(R.id.seekbar_audio);
final ClickListener clickListener = new ClickListener();
findViewById(R.id.button_previous).setOnClickListener(clickListener);
findViewById(R.id.button_play).setOnClickListener(clickListener);
findViewById(R.id.button_next).setOnClickListener(clickListener);
mMediaBrowserHelper = new MediaBrowserConnection(this);
mMediaBrowserHelper.registerCallback(new MediaBrowserListener());
}
#Override
public void onStart() {
super.onStart();
mMediaBrowserHelper.onStart();
}
#Override
public void onStop() {
super.onStop();
mSeekBarAudio.disconnectController();
mMediaBrowserHelper.onStop();
}
/**
* Convenience class to collect the click listeners together.
* <p>
* In a larger app it's better to split the listeners out or to use your favorite
* library.
*/
private class ClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_previous:
mMediaBrowserHelper.getTransportControls().skipToPrevious();
break;
case R.id.button_play:
if (mIsPlaying) {
mMediaBrowserHelper.getTransportControls().pause();
} else {
mMediaBrowserHelper.getTransportControls().play();
}
break;
case R.id.button_next:
mMediaBrowserHelper.getTransportControls().skipToNext();
break;
}
}
}
/**
* Customize the connection to our {#link android.support.v4.media.MediaBrowserServiceCompat}
* and implement our app specific desires.
*/
private class MediaBrowserConnection extends MediaBrowserHelper {
private MediaBrowserConnection(Context context) {
super(context, MusicService.class);
}
#Override
protected void onConnected(#NonNull MediaControllerCompat mediaController) {
mSeekBarAudio.setMediaController(mediaController);
}
#Override
protected void onChildrenLoaded(#NonNull String parentId,
#NonNull List<MediaBrowserCompat.MediaItem> children) {
super.onChildrenLoaded(parentId, children);
final MediaControllerCompat mediaController = getMediaController();
// Queue up all media items for this simple sample.
for (final MediaBrowserCompat.MediaItem mediaItem : children) {
mediaController.addQueueItem(mediaItem.getDescription());
}
// Call prepare now so pressing play just works.
mediaController.getTransportControls().prepare();
}
}
/**
* Implementation of the {#link MediaControllerCompat.Callback} methods we're interested in.
* <p>
* Here would also be where one could override
* {#code onQueueChanged(List<MediaSessionCompat.QueueItem> queue)} to get informed when items
* are added or removed from the queue. We don't do this here in order to keep the UI
* simple.
*/
private class MediaBrowserListener extends MediaControllerCompat.Callback {
#Override
public void onPlaybackStateChanged(PlaybackStateCompat playbackState) {
mIsPlaying = playbackState != null &&
playbackState.getState() == PlaybackStateCompat.STATE_PLAYING;
mMediaControlsImage.setPressed(mIsPlaying);
}
#Override
public void onMetadataChanged(MediaMetadataCompat mediaMetadata) {
if (mediaMetadata == null) {
return;
}
mTitleTextView.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
mArtistTextView.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST));
mAlbumArt.setImageBitmap(MusicLibrary.getAlbumBitmap(
MainActivity.this,
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)));
}
#Override
public void onSessionDestroyed() {
super.onSessionDestroyed();
}
#Override
public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
super.onQueueChanged(queue);
}
}
}
MusicLibrary Class where two sample songs
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import com.example.android.mediasession.BuildConfig;
import com.example.android.mediasession.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
public class MusicLibrary {
private static final TreeMap<String, MediaMetadataCompat> music = new TreeMap<>();
private static final HashMap<String, Integer> albumRes = new HashMap<>();
private static final HashMap<String, String> musicFileName = new HashMap<>();
static {
createMediaMetadataCompat(
"Jazz_In_Paris",
"Jazz in Paris",
"Media Right Productions",
"Jazz & Blues",
"Jazz",
103,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/2537.mp3",
R.drawable.album_jazz_blues,
"https://upload.wikimedia.org/wikipedia/en/a/ac/Audioslave_-_Audioslave.jpg");
createMediaMetadataCompat(
"The_Coldest_Shoulder",
"The Coldest Shoulder",
"The 126ers",
"Youtube Audio Library Rock 2",
"Rock",
160,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/4201.mp3",
R.drawable.album_youtube_audio_library_rock_2,
"https://theflagcompany.in/wp-content/uploads/2018/10/Indian-National-Flag-300x300.jpeg");
}
public static String getRoot() {
return "root";
}
private static String getAlbumArtUri(String albumArtResName) {
return ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
BuildConfig.APPLICATION_ID + "/drawable/" + albumArtResName;
}
public static String getMusicFilename(String mediaId) {
return musicFileName.containsKey(mediaId) ? musicFileName.get(mediaId) : null;
}
private static int getAlbumRes(String mediaId) {
return albumRes.containsKey(mediaId) ? albumRes.get(mediaId) : 0;
}
public static Bitmap getAlbumBitmap(Context context, String mediaId) {
return BitmapFactory.decodeResource(context.getResources(),
MusicLibrary.getAlbumRes(mediaId));
}
public static List<MediaBrowserCompat.MediaItem> getMediaItems() {
List<MediaBrowserCompat.MediaItem> result = new ArrayList<>();
for (MediaMetadataCompat metadata : music.values()) {
result.add(
new MediaBrowserCompat.MediaItem(
metadata.getDescription(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE));
}
return result;
}
public static MediaMetadataCompat getMetadata(Context context, String mediaId) {
MediaMetadataCompat metadataWithoutBitmap = music.get(mediaId);
Bitmap albumArt = getAlbumBitmap(context, mediaId);
// Since MediaMetadataCompat is immutable, we need to create a copy to set the album art.
// We don't set it initially on all items so that they don't take unnecessary memory.
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
for (String key :
new String[]{
MediaMetadataCompat.METADATA_KEY_MEDIA_ID,
MediaMetadataCompat.METADATA_KEY_ALBUM,
MediaMetadataCompat.METADATA_KEY_ARTIST,
MediaMetadataCompat.METADATA_KEY_GENRE,
MediaMetadataCompat.METADATA_KEY_TITLE
}) {
builder.putString(key, metadataWithoutBitmap.getString(key));
}
builder.putLong(
MediaMetadataCompat.METADATA_KEY_DURATION,
metadataWithoutBitmap.getLong(MediaMetadataCompat.METADATA_KEY_DURATION));
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt);
return builder.build();
}
private static void createMediaMetadataCompat(
String mediaId,
String title,
String artist,
String album,
String genre,
long duration,
TimeUnit durationUnit,
String musicFilename,
int albumArtResId,
String albumArtResName) {
music.put(
mediaId,
new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaId)
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, album)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION,
TimeUnit.MILLISECONDS.convert(duration, durationUnit))
.putString(MediaMetadataCompat.METADATA_KEY_GENRE, genre)
.putString(
MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI,
getAlbumArtUri(albumArtResName))
.putString(
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,
getAlbumArtUri(albumArtResName))
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
.build());
albumRes.put(mediaId, albumArtResId);
musicFileName.put(mediaId, musicFilename);
}
}
Please, can anybody help me with this?
I have a project using CameraBridgeViewBase and I want to take a picture and save a file, but CameraBridgeViewBase doesn't implement the function takePicture.
Result: I implemented a new class extends JavaCameraView and implemented myself the function takePicture.
import org.opencv.android.JavaCameraView;
import java.io.FileOutputStream;
import java.util.List;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.util.Log;
public class MyCameraView extends JavaCameraView implements PictureCallback {
private static final String TAG = "myCameraView";
private String mPictureFileName;
public MyCameraView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public List<String> getEffectList() {
return mCamera.getParameters().getSupportedColorEffects();
}
public boolean isEffectSupported() {
return (mCamera.getParameters().getColorEffect() != null);
}
public String getEffect() {
return mCamera.getParameters().getColorEffect();
}
public void setEffect(String effect) {
Camera.Parameters params = mCamera.getParameters();
params.setColorEffect(effect);
mCamera.setParameters(params);
}
public List<Size> getResolutionList() {
return mCamera.getParameters().getSupportedPreviewSizes();
}
public void setResolution(Size resolution) {
disconnectCamera();
mMaxHeight = resolution.height;
mMaxWidth = resolution.width;
connectCamera(getWidth(), getHeight());
}
public Size getResolution() {
return mCamera.getParameters().getPreviewSize();
}
public void takePicture(final String fileName) {
Log.i(TAG, "Taking picture");
this.mPictureFileName = fileName;
// Postview and jpeg are sent in the same buffers if the queue is not empty when performing a capture.
// Clear up buffers to avoid mCamera.takePicture to be stuck because of a memory issue
mCamera.setPreviewCallback(null);
// PictureCallback is implemented by the current class
mCamera.takePicture(null, null, this);
}
#Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i(TAG, "Saving a bitmap to file");
// The camera preview was automatically stopped. Start it again.
mCamera.startPreview();
mCamera.setPreviewCallback(this);
// Write the image in a file (in jpeg format)
try {
FileOutputStream fos = new FileOutputStream(mPictureFileName);
fos.write(data);
fos.close();
} catch (java.io.IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
}
-
private MyCameraView mOpenCvCameraView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mOpenCvCameraView = (MyCameraView) view.findViewById(R.id.fd_activity_surface_view);
mOpenCvCameraView.setCvCameraViewListener(this);
return view;
}
#Override
public void onResume() {
super.onResume();
mOpenCvCameraView.enableView();
String filename = "teste.jpg";
mOpenCvCameraView.takePicture(filename);
mOpenCvCameraView.disableView();
}
I'm having trouble implementing this color picker into my live wallpaper. It works just fine out of the box by itself (I can add it to my preferences menu, open up the widget and select a color), however I want to use that selected color to detail an EditText field that the user will see on the homescreen canvas. I can easily achieve this by changing ColorDialogPreference.java's int color to a static variable and calling it from the WallpaperService class directly:
int mColor = com.my.app.ColorDialogPreference.color;
But since it's static, the color gets reset once the process gets destroyed.
I've tried saving the variable via a SharedPreferences Editor inside my PreferencesActivity.java (see below), but can't seem to retrieve that variable in the WallpaperService class.
PreferencesActivity.java:
package com.my.app;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
public class MyPreferencesActivity extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
#SuppressWarnings("deprecation")
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences preferences =
getSharedPreferences("prefs", MODE_WORLD_WRITEABLE);
getPreferenceManager().setSharedPreferencesName("preferenceKeyName");
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("preferenceKeyName", Color.GRAY);
editor.commit();
getPreferenceManager().setSharedPreferencesName("text_to_display");
getPreferenceManager().getSharedPreferences().
registerOnSharedPreferenceChangeListener(this);
addPreferencesFromResource(R.xml.prefs);
}
#SuppressWarnings("deprecation")
protected void onDestroy() {
getPreferenceManager().getSharedPreferences().
unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
#SuppressWarnings("deprecation")
protected void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().
registerOnSharedPreferenceChangeListener(this);
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
getPreferenceManager().getSharedPreferences().
registerOnSharedPreferenceChangeListener(this);
}
}
WallpaperService.java:
package com.my.app;
import java.util.List;
import java.util.Random;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.service.wallpaper.WallpaperService;
import android.view.SurfaceHolder;
public class MyWallpaperService extends WallpaperService {
public MyWallpaperService() {
super();
}
#Override
public Engine onCreateEngine() {
return new MyWallpaperEngine();
}
public class MyWallpaperEngine extends Engine
implements OnSharedPreferenceChangeListener {
Context ctx = getApplicationContext();
SharedPreferences sharedPreferences2 =
getSharedPreferences("prefs", MODE_WORLD_READABLE);
private int mColor = sharedPreferences2.getInt("preferenceKeyName",
Color.RED);
private boolean mVisible = false;
Paint p = new Paint();
float x1 = 0;
float y1 = 60;
private final Handler mHandler = new Handler();
private final Runnable mUpdateDisplay = new Runnable() {
#Override
public void run() {
draw();
}};
private void draw() {
SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
String text = "1. " + mText;
c.drawRect(0, 0, c.getWidth(), c.getHeight(), p);
p.setColor(mColor);
c.drawText(text, x, y, p);
}
}
}
} finally {
if (c != null)
holder.unlockCanvasAndPost(c);
}
mHandler.removeCallbacks(mUpdateDisplay);
if (mVisible) {
mHandler.postDelayed(mUpdateDisplay, 16);
}
}
private final Handler handler = new Handler();
private final Runnable drawRunner = new Runnable() {
#Override
public void run() {
draw();
}
};
#Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
mVisible = visible;
if (visible) {
mText = sharedPreferences.getString("text_to_display",
"default");
draw();
} else {
mHandler.removeCallbacks(mUpdateDisplay);
}
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
mVisible = false;
handler.removeCallbacks(drawRunner);
mHandler.removeCallbacks(mUpdateDisplay);
}
#Override
public void onDestroy() {
super.onDestroy();
mVisible = false;
mHandler.removeCallbacks(mUpdateDisplay);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
draw();
}
}
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
// TODO Auto-generated method stub
}
}
}
And my prefs.xml:
`<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen android:title="Set Text" android:summary="Some summary" >
<EditTextPreference android:key="text_to_display" android:title="Some text" />
</PreferenceScreen>
<PreferenceScreen android:title="Colors" android:summary="Any color you want!" >
<com.my.app.ColorPickerPreference
android:defaultValue="0xffffffff"
android:key="preferenceKeyName"
android:title="#string/pref_name"
android:summary="#string/pref_summary" />
</PreferenceScreen>
</PreferenceScreen>`
If I display the value of int color on the canvas, all that ever comes up is "-65535". I know that PreferencesActivity works to some degree, because retrieving "text_to_display", which is an EditText value, works just fine. Something else that is worth noting: if the process gets killed at all (reboot phone or FC), the color that I selected in the widget stays that color if I go back to the widget after having the process killed, so it seems to be saving inside ColorDialogPreference.java, but nowhere else?
Please consider using this color picker: github.com/chiralcode/Android-Color-Picker. It can be used as a preference on PreferenceScreen. Value will be stored in shared preferences with the key you provided.
You should also consider cleaning up your code. My proposition is to change MyPreferencesActivity into this:
public class MyPreferencesActivity extends PreferenceActivity {
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getPreferenceManager().setSharedPreferencesName("sharedPreferencesFilename");
addPreferencesFromResource(R.xml.prefs);
}
}
This is all the code you need. It looks like that you do not fully understand how shared preferences works.
Your code doesn't work, because you are writing preferences to files such as "preferenceKeyName" and "text_to_display", but you are reading them from "prefs".
I am using mapview in my android app
using the class com.google.android.maps
I wont lo load markers using background process when the user navigate I want to
send the Viewport coordinate to my server
I can do it in javascript like here
google.maps.event.addListener(map, 'idle', showMarkers);
function showMarkers() {
var bounds = map.getBounds();
// Call you server with ajax passing it the bounds
// In the ajax callback delete the current markers and add new markers
}
But how can I do this in java ? Please suggest.
i post this answer and i hope to save some one else time
i found that the best solution for my case is to use custom map view SimpleMapView
first crete the SimpleMapView class in your project and here is the code
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
public class SimpleMapView extends MapView {
private int currentZoomLevel = -1;
private GeoPoint currentCenter;
private List<ZoomChangeListener> zoomEvents = new ArrayList<ZoomChangeListener>();
private List<PanChangeListener> panEvents = new ArrayList<PanChangeListener>();
public SimpleMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public SimpleMapView(Context context, String apiKey) {
super(context, apiKey);
}
public SimpleMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
*
* #return
*/
public int[][] getBounds() {
GeoPoint center = getMapCenter();
int latitudeSpan = getLatitudeSpan();
int longtitudeSpan = getLongitudeSpan();
int[][] bounds = new int[2][2];
bounds[0][0] = center.getLatitudeE6() - (latitudeSpan / 2);
bounds[0][1] = center.getLongitudeE6() - (longtitudeSpan / 2);
bounds[1][0] = center.getLatitudeE6() + (latitudeSpan / 2);
bounds[1][1] = center.getLongitudeE6() + (longtitudeSpan / 2);
return bounds;
}
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
GeoPoint centerGeoPoint = this.getMapCenter();
if (currentCenter == null ||
(currentCenter.getLatitudeE6() != centerGeoPoint.getLatitudeE6()) ||
(currentCenter.getLongitudeE6() != centerGeoPoint.getLongitudeE6()) ) {
firePanEvent(currentCenter, this.getMapCenter());
}
currentCenter = this.getMapCenter();
}
return super.onTouchEvent(ev);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(getZoomLevel() != currentZoomLevel){
fireZoomLevel(currentZoomLevel, getZoomLevel());
currentZoomLevel = getZoomLevel();
}
}
#Override
public void setSatellite(boolean on){
super.setSatellite(on);
}
#Override
public MapController getController(){
return super.getController();
}
private void fireZoomLevel(int old, int current){
for(ZoomChangeListener event : zoomEvents){
event.onZoom(old, current);
}
}
private void firePanEvent(GeoPoint old, GeoPoint current){
for(PanChangeListener event : panEvents){
event.onPan(old, current);
}
}
public void addZoomChangeListener(ZoomChangeListener listener){
this.zoomEvents.add(listener);
}
public void addPanChangeListener(PanChangeListener listener){
this.panEvents.add(listener);
}
}
and in your mapactivity just make
SimpleMapView mapView = (SimpleMapView) findViewById(R.id.mapView);
and then you have
mapView.addPanChangeListener(new PanChangeListener() {
#Override
public void onPan(GeoPoint old, GeoPoint current) {
//TODO
//do your work here
}
});
and add the PanChangeListener class here the code
package yourPkageName;
import com.google.android.maps.GeoPoint;
public interface PanChangeListener {
public void onPan(GeoPoint old, GeoPoint current);
}
and add the ZoomChangeListener class here the code
package yourPkageName;
public interface ZoomChangeListener {
public void onZoom(int old, int current);
}
and in your xml file add
<?xml version="1.0" encoding="utf-8"?>
<YourPakageName.SimpleMapView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:apiKey="0mAbU5bZyFY2I46PFJ1ysXGcYlAmFM6fYBWSB7Q"
android:clickable="true" />
I am working on something that needed custom drag-and-drop functionality, so I have been subclassing View, doing a bunch of math in response to touch events, and then rendering everything manually through code on the canvas in onDraw. Now, the more functionality I add, the more the code is growing out of control and I find myself writing a ton more code than I would expect to write in a high level environment like Android.
Is this how it's done, or am I missing something? If I'm not doing anything fancy in the UI, the framework handles the majority of my interactions. Built-in controls handle the touches and drags, and my code is pretty much limited to business logic and data. Is there a way to leverage the power of some of the UI controls and things like animations while also doing some of it manually in the onDraw canvas? Is there an accepted standard of when to use one or the other (if indeed the two approaches can be mixed)?
I use drag and drop in my music player application! I give to user the ability to move an song from an playlist to an other playlist. It is really nice and simple for the user. I start the drag event for my view when user make an long tap on an song or when an option from an menu is selected!
This is my class:
package com.liviu.app.smpp.gui;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.liviu.app.smpp.R;
import com.liviu.app.smpp.listeners.CollisionListener;
public class SongItemView extends RelativeLayout implements OnClickListener {
// data
private String TAG = "SongItemView";
private Context context;
private LayoutInflater lInflater;
private String title;
private int id;
private int maxHeight = 410;
private int mCurX;
private int mCurY;
//listeners
private CollisionListener onCollisionListener = null;
// views
private View v;
public SongItemView(Context ctx, String title_, int id_) {
super(ctx);
context = ctx;
lInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = lInflater.inflate(R.layout.song_item_view, null);
title = title_;
id = id_;
((TextView)v.findViewById(R.id.siv_title)).setText(title);
addView(v, new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
#Override
public void onClick(View v) {
Log.e(TAG, "clicked! " + ((TextView)v.findViewById(R.id.piv_title)).getText().toString());
}
public View getView(){
return v;
}
public String getPlsName() {
return title;
}
public int getID() {
return id;
}
public void setTitle(String title_){
((TextView)v.findViewById(R.id.siv_title)).setText(title_);
title = title_;
}
public void setID(int id_) {
id = id_;
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
mCurX = (int) event.getRawX();
mCurY = (int) event.getRawY();
int action = event.getAction();
if (action == MotionEvent.ACTION_MOVE)
{
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.leftMargin = mCurX;
params.topMargin = mCurY;
this.setLayoutParams(params);
if(this.getTop() >= maxHeight)
{
Log.e(TAG, "Collision!!!!");
if(onCollisionListener != null){
onCollisionListener.onCollision(this);
}
}
}
return true;
}
public void setOnCollisionListener(CollisionListener listener){
onCollisionListener = listener;
}
public void setMaxHeight(int height){
maxHeight = height;
}
public int getmCurX() {
return mCurX;
}
public int getmCurY() {
return mCurY;
}
public int getMaxHeight() {
return maxHeight;
}
}
I hope this will help a bit.
Thanks!