কম্পিউটার টিউটোরিয়াল

অ্যান্ড্রয়েড GPS এবং লোকেশন ম্যানেজার টিউটোরিয়াল

এই উদাহরণটি দেখায় কিভাবে অ্যান্ড্রয়েড GPS এবং লোকেশন ম্যানেজার অ্যাক্সেস করতে হয়।

ধাপ ১: নতুন প্রজেক্ট তৈরি করুন

Android Studio-তে File → New Project এ যান এবং প্রজেক্ট তৈরি করার জন্য সকল প্রয়োজনীয় তথ্য পূরণ করুন।

ধাপ ২: লেআউট XML ফাইল যোগ করুন

res/layout/activity_main.xml ফাইলে নিচের কোডটি যোগ করুন:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_start_location_updates"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:onClick="startLocationButtonClick"
        android:text="@string/start_updates" />

    <Button
        android:id="@+id/btn_stop_location_updates"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:enabled="false"
        android:onClick="stopLocationButtonClick"
        android:text="@string/stop_updates" />

    <Button
        android:id="@+id/btn_get_last_location"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:onClick="showLastKnownLocation"
        android:text="@string/get_last_location" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:gravity="center_horizontal"
        android:text="Location updates will be received only when app is foreground" />

    <TextView
        android:id="@+id/location_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textColor="#333"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/updated_on"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:textSize="12sp" />

</LinearLayout>

ধাপ ৩: MainActivity.java ফাইলে কোড যোগ করুন

src/MainActivity.java ফাইলে নিচের কোডটি যোগ করুন। এই ক্লাসটি FusedLocationProviderClient ব্যবহার করে লোকেশন আপডেট পরিচালনা করে।

package app.com.sample;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionDeniedResponse;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.single.PermissionListener;
import java.text.DateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();
    TextView txtLocationResult;
    TextView txtUpdatedOn;
    Button btnStartUpdates;
    Button btnStopUpdates;
    
    // লোকেশন শেষ কখন আপডেট হয়েছিল
    private String mLastUpdateTime;
    
    // লোকেশন আপডেট ইন্টারভাল - ১০ সেকেন্ড
    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
    
    // দ্রুততম আপডেট ইন্টারভাল - ৫ সেকেন্ড
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 5000;
    private static final int REQUEST_CHECK_SETTINGS = 100;
    
    // লোকেশন সম্পর্কিত API গুলো
    private FusedLocationProviderClient mFusedLocationClient;
    private SettingsClient mSettingsClient;
    private LocationRequest mLocationRequest;
    private LocationSettingsRequest mLocationSettingsRequest;
    private LocationCallback mLocationCallback;
    private Location mCurrentLocation;
    
    // UI টগল করার জন্য বুলিয়ান ফ্ল্যাগ
    private Boolean mRequestingLocationUpdates;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // প্রয়োজনীয় লাইব্রেরি ইনিশিয়ালাইজ করুন
        init();
        // সংরক্ষিত ইনস্ট্যান্স স্টেট থেকে মান পুনরুদ্ধার করুন
        restoreValuesFromBundle(savedInstanceState);
    }

    private void init() {
        txtLocationResult = findViewById(R.id.location_result);
        txtUpdatedOn = findViewById(R.id.updated_on);
        btnStartUpdates = findViewById(R.id.btn_start_location_updates);
        btnStopUpdates = findViewById(R.id.btn_stop_location_updates);
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        mSettingsClient = LocationServices.getSettingsClient(this);
        
        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                // লোকেশন পাওয়া গেলে
                mCurrentLocation = locationResult.getLastLocation();
                mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
                updateLocationUI();
            }
        };
        
        mRequestingLocationUpdates = false;
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        mLocationSettingsRequest = builder.build();
    }

    /** সংরক্ষিত ইনস্ট্যান্স স্টেট থেকে মান পুনরুদ্ধার করা */
    private void restoreValuesFromBundle(Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            if (savedInstanceState.containsKey("is_requesting_updates")) {
                mRequestingLocationUpdates = savedInstanceState.getBoolean("is_requesting_updates");
            }
            if (savedInstanceState.containsKey("last_known_location")) {
                mCurrentLocation = savedInstanceState.getParcelable("last_known_location");
            }
            if (savedInstanceState.containsKey("last_updated_on")) {
                mLastUpdateTime = savedInstanceState.getString("last_updated_on");
            }
        }
        updateLocationUI();
    }

    /** লোকেশন ডেটা প্রদর্শন করে UI আপডেট করা এবং বাটন টগল করা */
    private void updateLocationUI() {
        if (mCurrentLocation != null) {
            txtLocationResult.setText(
                "Lat: " + mCurrentLocation.getLatitude() + ", " +
                "Lng: " + mCurrentLocation.getLongitude()
            );
            // TextView-এ ব্লিংক অ্যানিমেশন দিন
            txtLocationResult.setAlpha(0);
            txtLocationResult.animate().alpha(1).setDuration(300);
            // লোকেশন শেষ আপডেট হওয়ার সময়
            txtUpdatedOn.setText("Last updated on: " + mLastUpdateTime);
        }
        toggleButtons();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean("is_requesting_updates", mRequestingLocationUpdates);
        outState.putParcelable("last_known_location", mCurrentLocation);
        outState.putString("last_updated_on", mLastUpdateTime);
    }

    private void toggleButtons() {
        if (mRequestingLocationUpdates) {
            btnStartUpdates.setEnabled(false);
            btnStopUpdates.setEnabled(true);
        } else {
            btnStartUpdates.setEnabled(true);
            btnStopUpdates.setEnabled(false);
        }
    }

    /** লোকেশন আপডেট শুরু করা
     * চেক করুন যে লোকেশন সেটিংস সন্তুষ্ট হয়েছে কিনা এবং তারপর
     * লোকেশন আপডেট অনুরোধ করুন */
    private void startLocationUpdates() {
        mSettingsClient
            .checkLocationSettings(mLocationSettingsRequest)
            .addOnSuccessListener(this, new OnSuccessListener() {
                @SuppressLint("MissingPermission")
                @Override
                public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                    Log.i(TAG, "All location settings are satisfied.");
                    Toast.makeText(getApplicationContext(), "Started location updates!", Toast.LENGTH_SHORT).show();
                    //noinspection MissingPermission
                    mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
                    updateLocationUI();
                }
            })
            .addOnFailureListener(this, new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    int statusCode = ((ApiException) e).getStatusCode();
                    switch (statusCode) {
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade location settings ");
                            try {
                                // startResolutionForResult() কল করে ডায়ালগ দেখান, এবং
                                // onActivityResult()-এ ফলাফল চেক করুন।
                                ResolvableApiException rae = (ResolvableApiException) e;
                                rae.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
                            } catch (IntentSender.SendIntentException sie) {
                                Log.i(TAG, "PendingIntent unable to execute request.");
                            }
                            break;
                        case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                            String errorMessage = "Location settings are inadequate, and cannot be fixed here. Fix in Settings.";
                            Log.e(TAG, errorMessage);
                            Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_LONG).show();
                    }
                    updateLocationUI();
                }
            });
    }

    public void startLocationButtonClick(View view) {
        // Dexter লাইব্রেরি ব্যবহার করে ACCESS_FINE_LOCATION অনুমতি অনুরোধ
        Dexter.withActivity(this)
            .withPermission(Manifest.permission.ACCESS_FINE_LOCATION)
            .withListener(new PermissionListener() {
                @Override
                public void onPermissionGranted(PermissionGrantedResponse response) {
                    mRequestingLocationUpdates = true;
                    startLocationUpdates();
                }
                @Override
                public void onPermissionDenied(PermissionDeniedResponse response) {
                    if (response.isPermanentlyDenied()) {
                        // যখন অনুমতি স্থায়ীভাবে অস্বীকৃত হয়, ডিভাইস সেটিংস খুলুন
                        openSettings();
                    }
                }
                @Override
                public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
                    token.continuePermissionRequest();
                }
            }).check();
    }

    public void stopLocationButtonClick(View view) {
        mRequestingLocationUpdates = false;
        stopLocationUpdates();
    }

    public void stopLocationUpdates() {
        // লোকেশন আপডেট সরানো
        mFusedLocationClient
            .removeLocationUpdates(mLocationCallback)
            .addOnCompleteListener(this, new OnCompleteListener() {
                @Override
                public void onComplete(@NonNull Task task) {
                    Toast.makeText(getApplicationContext(), "Location updates stopped!", Toast.LENGTH_SHORT).show();
                    toggleButtons();
                }
            });
    }

    public void showLastKnownLocation(View view) {
        if (mCurrentLocation != null) {
            Toast.makeText(getApplicationContext(), "Lat: " + mCurrentLocation.getLatitude() + ", Lng: " + mCurrentLocation.getLongitude(), Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(getApplicationContext(), "Last known location is not available!", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // startResolutionForResult()-এ মূলরূপে দেওয়া ইন্টিজার রিকোয়েস্ট কোড চেক করুন।
        if (requestCode == REQUEST_CHECK_SETTINGS) {
            switch (resultCode) {
                case Activity.RESULT_OK:
                    Log.e(TAG, "User agreed to make required location settings changes.");
                    // কিছু করতে নেই। onResume-এ আবার startLocationupdates() কল হবে।
                    break;
                case Activity.RESULT_CANCELED:
                    Log.e(TAG, "User chose not to make required location settings changes.");
                    mRequestingLocationUpdates = false;
                    break;
            }
        }
    }

    private void openSettings() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", BuildConfig.APPLICATION_ID, null);
        intent.setData(uri);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    @Override
    public void onResume() {
        super.onResume();
        // বাটন স্টেট এবং অনুমোদিত অনুমতির উপর নির্ভর করে লোকেশন আপডেট পুনরায় শুরু
        if (mRequestingLocationUpdates && checkPermissions()) {
            startLocationUpdates();
        }
        updateLocationUI();
    }

    private boolean checkPermissions() {
        int permissionState = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
        return permissionState == PackageManager.PERMISSION_GRANTED;
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mRequestingLocationUpdates) {
            // লোকেশন আপডেট বিরত রাখা
            stopLocationUpdates();
        }
    }
}

ধাপ ৪: AndroidManifest.xml-এ অনুমতি যোগ করুন

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="app.com.sample">
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

অ্যাপ্লিকেশন চালান

আপনার অ্যান্ড্রয়েড মোবাইল ডিভাইস কম্পিউটারের সাথে সংযুক্ত আছে ধরে নেওয়া হয়েছে। Android Studio-তে আপনার প্রজেক্টের যেকোনো এক্টিভিটি ফাইল খুলুন এবং টুলবার থেকে Run আইকনে ক্লিক করুন। আপনার মোবাইল ডিভাইস সিলেক্ট করুন এবং ডিভাইসে ডিফল্ট স্ক্রিন দেখুন।

  1. GPS লোকেশন নকল করার ৭টি সেরা ফ্রি অ্যান্ড্রয়েড অ্যাপ

  2. অ্যান্ড্রয়েড ডিভাইসে GPS লোকেশন সিমুলেট করার পদ্ধতি

  3. অ্যান্ড্রয়েড ডিভাইসে GPS লোকেশন সফলভাবে স্পুফ করার পদ্ধতি

  4. অ্যান্ড্রয়েডের জন্য সেরা ৬টি বিশ্বস্ত ফেক GPS অ্যাপ - নিরাপদ এবং নির্ভরযোগ্য লোকেশন স্পুফিং