+1

Location-Based Services trong Android (phần 2)

Location-Based Services trong Android (phần 2)


**Ở phần 1 tôi đã đề cập đến các vấn đề:** * Làm sao để hiển thị Google maps vào trong ứng dụng của bạn? * Làm sao để hiển thị bảng điều khiển Zoon to, nhỏ trên map * Làm sao để chuyển đổi được các loại map views khác nhau * Làm sao thêm được marker trên map

Bạn có thể theo dõi phần 1 tại đây

Trong phần 2 này tôi sẽ tiếp tục với các nội dung như sau:

  1. Làm thế nào để lấy được địa chỉ trên map khi chạm vào
  2. Làm thế nào để mã hóa vị trí địa lý mà mã hóa địa lý đảo ngược
  3. Làm thế nào để lấy được vị trí địa lý sử dụng GPS, Cell-ID, Wifi
  4. Làm thế nào để theo dõi được vị trí

1. Lấy địa chỉ trên map khi có sự kiện 'Touche'


Để xác định vị trí tọa độ` latitude` và` longitude` tương ứng trên màn hình khi bạn chạm vào màn hình bạn có thế sử dụng `onTouchEvent() `method trong `MapOverlay `class (Nếu bạn đã thêm `Overlay` trên map của mình như đã trình bày ở phần 1). Phương thức này sẽ được gọi ra mỗi lần người dùng Tab vào màn hình.

Phương thức này gồm có 2 parameters: MotionEventMapView.

Sử dụng MotionEventparameter bạn có thể phát hiện ra sự kiên người dùng nhả tay ra khỏi màn hình bằng phương thức getAction().

Tiến hành ví dụ sau để hiển thị ra vị trí địa lý (latitude và longitude) khi người dùng chạm vào map và nhả tay ra:

import android.view.MotionEvent;
import android.widget.Toast;

    class MapOverlay extends com.google.android.maps.Overlay
    {
        @Override
        public boolean draw(Canvas canvas, MapView mapView,
        boolean shadow, long when)
        {
            super.draw(canvas, mapView, shadow);
            //---chuyển đổi GeoPoint thành dạng screen pixels---
            Point screenPts = new Point();
            mapView.getProjection().toPixels(p, screenPts);
            //---thêm marker trên maps---
            Bitmap bmp = BitmapFactory.decodeResource(
                getResources(), R.drawable.pushpin);
            canvas.drawBitmap(bmp, screenPts.x, screenPts.y-50, null);
            return true;
        }
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView)
    {
        //---khi người dùng thả ngón tay ra khỏi màn hình---
        if (event.getAction() == 1) {
            GeoPoint p = mapView.getProjection().fromPixels(
                (int) event.getX(),
                (int) event.getY());
                Toast.makeText(getBaseContext(),Location:+
                    p.getLatitudeE6() / 1E6 +,+
                    p.getLongitudeE6() /1E6 ,
                    Toast.LENGTH_SHORT).show();
        }
    return false;
    }
}

Phương thức getProjection()sẽ trả ra một hệ quy chiếu để chuyển đổi giữa tọa độ màn hình và tọa độ kinh độ vĩ độ. Sau đo Phương thức fromPixels()sẽ chuyển đổi tọa độ này thành 1 đối tượng GeoPoint.

Và kết quả là:

alt


2. Mã hóa vị trí địa lí và Ngược lại'


Như đã đề cập trước đó, Bạn có thể tim được địa chỉ thông qua tọa độ (kinh độ/ vĩ độ). Google Máp trong Android hỗ trợ điều này thông qua Class `Geocoder`.
Xem xet ví dụ sau đây để lấy được địa chỉ khi chạm vào bản đồ sử dụng phương thức `getFromLocation()` :
import android.location.Address;
import android.location.Geocoder;
import java.util.Locale;
import java.io.IOException;
      @Override
        public boolean onTouchEvent(MotionEvent event, MapView mapView)
        {
            //---Khi người dùng nhả tay ra khỏi màn hình---
            if (event.getAction() == 1) {
                GeoPoint p = mapView.getProjection().fromPixels(
                    (int) event.getX(),
                    (int) event.getY());
                Geocoder geoCoder = new Geocoder(
                    getBaseContext(), Locale.getDefault());
            try {
                List<Address> addresses = geoCoder.getFromLocation(
                p.getLatitudeE6() / 1E6,
                p.getLongitudeE6() / 1E6, 1);
                String add = “”;
                if (addresses.size() > 0)
                    {
                        for (int i=0; i<addresses.get(0).getMaxAddressLineIndex(); i++)
                        add += addresses.get(0).getAddressLine(i) + “\n”;
                    }
                Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return true;
            }
            return false;
        }
    }

Đối tượng Geocoder sẽ chuyển đổi kinh độ và vĩ độ thành một địa chỉ địa lý sử dụng phương thức getFromLocation().

Địa chỉ thu được tôi sẽ hiển thị bằng một đối tượng thuộc classToast:

Kết qủa thu được:

alt

Tương tự như vậy. Android cũng cung cấp phương thức getFromLocationName() để Mã hóa ngược lại từ địa chỉ địa lý thành tọa độ vệ tinh.

//---geo-coding---
Geocoder geoCoder = new Geocoder(this, Locale.getDefault());
try {
    List<Address> addresses = geoCoder.getFromLocationName(
        “empire state building”, 5);
    String add = “”;
    if (addresses.size() > 0)
        {
            p = new GeoPoint(
            (int) (addresses.get(0).getLatitude() * 1E6),
            (int) (addresses.get(0).getLongitude() * 1E6));
            mc.animateTo(p);
            mapView.invalidate();
        }
    } catch (IOException e) {
        e.printStackTrace();
}


**Kết quả:**

alt

3. Lấy vị trí địa lý từ GPS, Cell-ID và Wifi

Ngày nay, Những thiết bị Mobile được tích hợp thêm tính năng Thu tín hiệuGPS (Global Positioning System - Hệ thống định vị toàn cầu) rất phổ biến. Bởi vì rất nhiều vệ tinh đang quay quanh trái đất. Bạn có thể sử dùng một Tín hiệu từ GPS để định vị vị trí của bạn một cách dễ dàng. Tuy nhiên GPS yêu cầu phải hoạt động trong môi trường tốt, không có địa hình như đồi núi hoặc ở trong phòng kín, thang máy....

Một cách khác để có thể định ví được vị trí của bạn đó là thông quaCell Tower Triangulation. Khi điện thoại được bật lên, nó sẽ liên tục phát ra tín hiệu liên lạc với các trạm xung quanh nó. Khi biết được địa chỉ của trung tâm, nó có thể cho phép truyền thông tin vị trí địa lý thông qua việc sử dụng Databases chứa danh tính và vị trí địa lý chính xác của trung tâm tháp di dộng. Tính năng nổi trội của Cell Tower Triangulation là nó có thể hoạt động ở trong phòng kín, đồi núi mà ko cần dữ liệu vệ tinh. Mặc dù vậy, Việc sử dụng Cel Tower lại không chính xác bằng sử dụng GPS vì nó phụ thuộc vào việc chồng chéo dữ liệu giữa các trạm, Cell tower hoạt động tốt nhất tại những nơi đông dân cư và có nhiều trạm thu dữ liệu.

Cách thứ ba để định vị vị trí của bạn là dựa vào` Wifi triangulation . Nó tốt hơn so với việc connect tới một cell tower, thiết bị của bạn sẽ kết nối với một mạng Wifi và kiểm tra dịch vụ cung cấp lại cơ sở dữ liệu để xác định lại vị trí của bạn.

Trong ba phương pháp nói trên, Định vị bằng việc kết nối với Wifi triangulation là chính xác nhất.

Trong Android, SDK cung cấp Class LocationManager để hỗ trợ thiết bị của bạn xác định vị trí của người dùng.

Xem xét ví dụ sau:


MainActivity.java file:
package net.learn2develop.LBS;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
public class MainActivity extends MapActivity {
    MapView mapView;
    MapController mc;
    GeoPoint p;
private LocationManager lm;
private LocationListener locationListener;
    class MapOverlay extends com.google.android.maps.Overlay
    {
        //...
    }
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mapView = (MapView) findViewById(R.id.mapView);
        mapView.setBuiltInZoomControls(true);
        mc = mapView.getController();
        String coordinates[] = {1.352566007,103.78921587};
        double lat = Double.parseDouble(coordinates[0]);
        double lng = Double.parseDouble(coordinates[1]);
        p = new GeoPoint(
            (int) (lat * 1E6),
            (int) (lng * 1E6));
        mc.animateTo(p);
        mc.setZoom(13);
        lm = (LocationManager)
        getSystemService(Context.LOCATION_SERVICE);
        locationListener = new MyLocationListener();
        lm.requestLocationUpdates(
        LocationManager.GPS_PROVIDER,0,0,locationListener);
    }
    private class MyLocationListener implements LocationListener
        {
            @Override
            public void onLocationChanged(Location loc) {
            if (loc != null)
                {
                    Toast.makeText(getBaseContext(),Location changed : Lat:+ loc.getLatitude() +Lng:+ loc.getLongitude(),
                        Toast.LENGTH_SHORT).show();
                }
            p = new GeoPoint(
            (int) (loc.getLatitude() * 1E6),
            (int) (loc.getLongitude() * 1E6));
            mc.animateTo(p);
            mc.setZoom(18);
        }
    @Override
    public void onProviderDisabled(String provider) {}
    @Override
    public void onProviderEnabled(String provider) {}
    @Override
    public void onStatusChanged(String provider, int status,Bundle extras) {}
}
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        //...
    }
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
}

Chú ý:

Nếu sử dụng Emulator thì bạn phải tự gửi dữ liệu GPS và nhận nó sử dụng Lacation Controls tool.

Vào Devices tab chọn Manlual tab nhập kinh độ vĩ độ và click nút Send như hình dưới

alt

Kết quả:

alt

Giải thích ví dụ:

Trong Android, location-base cung cấp bởi Class LocationManager nằm trong package android.location.

Để sử dụng class này trong ứng dụng này, đầu tiện bạn lấy vị trí hiện tại của bạn bằng phương thức getSystemService(). Để lấy được vị trí thay đổi mỗi khi bạn di chuyển thì bạn phải đăng ký một request cho location changes thông qua phương thức requestLocationUpdates().

lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);

trong đó:

provider - Tên của dịch vụ mà bạn muốn đăng ký. vi dụ GPS.

minTime - Khoảng thời gian tối thiểu hiện thông báo (đơn vị là mili giây)

minDisstance - Khoảng cách tối thiểu để hiện thông báo (đơn vị là mét)

listener - một đối tượng sẽ được gọi mỗi lần location được update.

Chú ý:

Nếu bạn muốn thay đổi Dịch vụ khác để định vị vị trí của bạn bạn chỉ cần thay đổi provider. ví dụ:

lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,0,locationListener);

Bạn cũng có thể sử dụng đồng thời các dịnh vụ trên trong cùng 1 ứng dụng.

4. Theo dõi một vị trí

Một tính năng khác mà Class LocationManager cũng cấp đó là một địa điểm đặc biệt. Bạn có thể làm được điều này nhờ sự trợ giups của phương thức addPriximitAlert().

Đọan code dưới đây cho thấy làm thế nào để theo dõi một địa điểm cụ thể để nếu người sử dụng nằm trong vòng bán kính năm mét từ vị trí của bạn. ứng dụng của bạn sẽ bắn ra một intent tới web browser:

//---use the LocationManager class to obtain locations data---
        lm = (LocationManager)
            getSystemService(Context.LOCATION_SERVICE);
//---PendingIntent to launch activity if the user is within some locations---
PendingIntent pendIntent = PendingIntent.getActivity(
this, 0, new
Intent(android.content.Intent.ACTION_VIEW,
Uri.parse(“http://www.amazon.com”)), 0);
lm.addProximityAlert(37.422006, -122.084095, 5, -1, pendIntent);

Phương thức addProximitAlert gồm có 5 tham số: kinh độ, vĩ độ, bán kính(đơn vị mét),thời gian bắn ra thông báo, vàintent mà thông báo sẽ được bắn ra.

Tổng kết

Ở bài viết lần này tôi đã đề cập đến việc sử dụng Mapview để hiển thị Google Maps trên ứng dụng của bạn, tôi cũng đề cập đến việc làm sao để lấy được vị trí hiện tại của bạn thông qua GPS, Cell-ID, Wifi. Làm sao để chuyển đổi dữ liệu vệ tinh thành địa chỉ địa lý và ngược lại. Hi vọng bài viết dễ hiểu đối với bạn.

Cảm ơn đã dành thời đọc bài viết.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.