/Android_Navigation

πŸ”ŽEcho-Project μ•ˆλ“œλ‘œμ΄λ“œμš© λ„€λΉ„κ²Œμ΄μ…˜ (학ꡐ μ•ˆλ‚΄)

Primary LanguageJava

λ‹¨κ΅­λŒ€ 2021 Echo+ κ²½μ§„λŒ€νšŒ μš°μˆ˜μƒ

λͺ©μ°¨

  • μ–΄ν”Œμ†Œκ°œ
  • μ•ˆλ“œλ‘œμ΄λ“œ μŠ€νŠœλ””μ˜€
    • 둜그인 ν™”λ©΄
      • Firebase 연동
      • νšŒμ›κ°€μž… ν™”λ©΄ ꡬ성
      • 둜그인 ν™”λ©΄ ꡬ성
      • μ‚¬μš©μž 정보 λͺ¨λΈ 클래슀
    • λ§΅λ°•μŠ€ SDK μ„€μΉ˜
    • getRoute λ©”μ†Œλ“œ
    • λͺ©μ μ§€ μ„€μ • 방법
  • κ°œμ„ λ°©μ•ˆ

μ–΄ν”Œμ†Œκ°œ

DK GUIDE λŠ” 학ꡐ지리에 μ΅μˆ™μΉ˜ μ•Šμ€ μ‚¬μš©μžλ₯Ό μœ„ν•œ λ„€λΉ„κ²Œμ΄μ…˜ 기반 μ•±μœΌλ‘œμ¨ μ¦κ°•ν˜„μ‹€(AR) κΈ°μˆ μ„ ν™œμš©ν•˜μ—¬ μ‚¬μš©μžκ°€ 평면 지도λ₯Ό ν™œμš©ν•œ κΈΈμ°ΎκΈ° 방식보닀 보닀 μ‰½κ²Œ 길을 찾을 수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” κ°€μ΄λ“œμ•±μ΄λ‹€.

λ˜ν•œ μ‚¬μš©μžλŠ” ν•΄λ‹Ή λͺ©μ μ§€μ— λ„μ°©μ‹œ ν•΄λ‹Ή μœ„μΉ˜λ‚˜ 건물에 λŒ€ν•œ 짧은 정보λ₯Ό AR μ• λ‹ˆλ©”μ΄μ…˜ 캐릭터λ₯Ό 톡해 μŒμ„±μœΌλ‘œ 얻을 수 μžˆλ‹€.

μ‹œμ—°μ˜μƒ : https://youtu.be/Nrat-Xba-c8
AR-Navigation μ‹œμ—° μ˜μƒ : https://youtu.be/BZWZdZ82R8w
μ–΄ν”Œλ¦¬μΊμ΄μ…˜ μ†Œκ°œ pdf : μ΅œμƒμœ„ 폴더 poster.pdf

λ§΅λ°•μŠ€μ—μ„œ μ œκ³΅ν•˜λŠ” νŠœν† λ¦¬μ–Όμ„ μ€‘μ‹¬μœΌλ‘œ μ œμž‘λ˜μ—ˆλ‹€. μ°Έκ³  : https://docs.mapbox.com/help/tutorials/android-navigation-sdk/

λ‹¨κ΅­λŒ€ 2021 Echo+ κ²½μ§„λŒ€νšŒ μš°μˆ˜μƒ


μ•ˆλ“œλ‘œμ΄λ“œ μŠ€νŠœλ””μ˜€

둜그인 ν™”λ©΄ & νšŒμ›κ°€μž… ν™”λ©΄

Firebase λ₯Ό μ΄μš©ν•˜μ—¬ 이메일 νšŒμ›κ°€μž… & 둜그인 κΈ°λŠ₯ κ΅¬ν˜„

λ‘œκ·ΈμΈμ΄λ‚˜ νšŒμ›κ°€μž… 정보λ₯Ό κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ μ„œλ²„ ꡬ좕을 ν•΄μ•Όν•˜μ§€λ§Œ Firebase λž€ μ„œλ²„ ꡬ좕 과정을 κ±΄λ„ˆλ„κ³  자체적으둜 λ§Œλ“€μ–΄μ§„ ν΄λΌμš°λ“œ μ„œλ²„λ₯Ό λΉŒλ €μ„œ 그곳에 λ°μ΄ν„°λ² μ΄μŠ€λ‘œ νšŒμ›κ°€μž…κ³Ό 둜그인 과정을 κ°„νŽΈν•˜κ²Œ ν•΄μ£ΌλŠ” 일련의 과정을 μ„œν¬νŒ… ν•΄μ£ΌλŠ” ν΄λΌμš°λ“œ ν”Œλž«νΌμ΄λ‹€.

1. Firebase 연동

  1. μ•ˆλ“œλ‘œμ΄λ“œ μŠ€νŠœλ””μ˜€ λ‚΄ Tools - firebase - Authenticate λ₯Ό 톡해 Authenticate using a custom authenticate system 을 ν΄λ¦­ν•œ ν›„ μƒˆ ν”„λ‘œμ νŠΈλ₯Ό μƒμ„±ν•œλ‹€.
  2. μ•ˆλ“œλ‘œμ΄λ“œ μŠ€νŠœλ””μ˜€λ‘œ λŒμ•„μ™€μ„œ Add the Firebase Authentication SDK to your app 클릭 ν›„ Firebase κ΄€λ ¨ 쒅속성을 μΆ”κ°€ν•΄μ€€λ‹€.
  3. Realtime database μ—μ„œ database κ΄€λ ¨ ν…Œμ΄λΈ” 곡간을 생성해주기 μœ„ν•΄ 사진과 같이 κ·œμΉ™μ—μ„œ λ‹€μŒκ³Ό 같이 읽기 κΆŒν•œκ³Ό μ“°κΈ° κΆŒν•œμ„ true 섀정을 톡해 κ°€μ Έμ˜¨λ‹€.

image

  1. Realtime database 쒅속성을 μΆ”κ°€ν•˜κΈ° μœ„ν•΄ Add the realtime Database to your app 을 ν΄λ¦­ν•˜μ—¬μ€€λ‹€.

2. νšŒμ›κ°€μž… ν™”λ©΄ ꡬ성

  1. RegisterActivity λΌλŠ” μ΄λ¦„μ˜ empty activity λ₯Ό 생성해쀀 ν›„ activity_register.xml μ—μ„œμ΄λ©”μΌκ³Ό λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•  수 μžˆλŠ” EditText 와 κ°€μž…μž 정보λ₯Ό λ°μ΄ν„°λ² μ΄μŠ€μ— μ „λ‹¬ν•΄μ£ΌλŠ” 'κ°€μž…ν•˜κΈ°' λ²„νŠΌμ„ 화면에 μΆ”κ°€ν•΄μ€€λ‹€.
<?xml version="1.0" encoding="utf-8"?>  
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  xmlns:app="http://schemas.android.com/apk/res-auto"  
  xmlns:tools="http://schemas.android.com/tools"  
  android:layout_width="match_parent"  
  android:layout_height="match_parent"  
  tools:context=".RegisterActivity">  
  
 <EditText  android:id="@+id/et_email"  
  android:layout_width="300dp"  
  android:layout_height="40dp"  
  android:layout_marginTop="240dp"  
  android:ems="10"  
  android:hint="이메일을 μž…λ ₯ν•˜μ„Έμš”"  
  android:inputType="textEmailAddress"  
  app:layout_constraintEnd_toEndOf="parent"  
  app:layout_constraintStart_toStartOf="parent"  
  app:layout_constraintTop_toTopOf="parent" />  
  
 <EditText  android:id="@+id/et_pwd"  
  android:layout_width="300dp"  
  android:layout_height="40dp"  
  android:layout_marginTop="32dp"  
  android:ems="10"  
  android:hint="λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•˜μ„Έμš”.(6자리 이상)"  
  android:inputType="textPassword"  
  app:layout_constraintEnd_toEndOf="parent"  
  app:layout_constraintHorizontal_bias="0.498"  
  app:layout_constraintStart_toStartOf="parent"  
  app:layout_constraintTop_toBottomOf="@+id/et_email" />  
  
 <Button  android:id="@+id/btn_register"  
  android:layout_width="0dp"  
  android:layout_height="wrap_content"  
  android:text="νšŒμ›κ°€μž…"  
  app:layout_constraintBottom_toBottomOf="parent"  
  app:layout_constraintEnd_toEndOf="parent"  
  app:layout_constraintStart_toStartOf="parent" />  
</androidx.constraintlayout.widget.ConstraintLayout>
  1. RegisterActivity μ—μ„œ νšŒμ›κ°€μž…κ³Ό κ΄€λ ¨ν•œ Firebase 인증처리 μ„œλ²„μ— μ—°λ™μ‹œμΌœμ€„ 수 μžˆλŠ” 객체 νšŒμ›κ°€μž… λ²„νŠΌμ΄ 클릭될 λ•Œμ˜ μ˜΅μ…˜μ²˜λ¦¬ λ“±μ˜ μ½”λ“œλ₯Ό λ‹€μŒκ³Ό 같이 μΆ”κ°€ν•΄μ€€λ‹€. νšŒμ›κ°€μž…μ— 성곡할 μ‹œ 둜그인 ν™”λ©΄μœΌλ‘œ λ„˜μ–΄κ°€λ„λ‘ μ„€μ •λ˜μ—ˆλ‹€.
  
private FirebaseAuth mFirebaseAuth; //Firebase 인증처리  
private DatabaseReference mDatabaseRef; //μ‹€μ‹œκ°„ λ°μ΄ν„°λ² μ΄μŠ€ -> μ„œλ²„μ— μ—°λ™μ‹œν‚¬μˆ˜μžˆλŠ” 객체  
private EditText mEtEmail, mEtPwd; //νšŒμ›κ°€μž… μž…λ ₯ν•„λ“œ  
private Button mBtnRegister; //νšŒμ›κ°€μž… λ²„νŠΌ  
  
  
  
@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
  setContentView(R.layout.activity_register);  
  
  mFirebaseAuth = FirebaseAuth.getInstance(); //firebase μ΄μš©μ€€λΉ„ 끝  
  mDatabaseRef = FirebaseDatabase.getInstance().getReference("mapbox");  
  
  mEtEmail = findViewById(R.id.et_email);  
  mEtPwd = findViewById(R.id.et_pwd);  
  mBtnRegister = findViewById(R.id.btn_register);    
}
  1. νšŒμ›κ°€μž… λ²„νŠΌ 클릭 μ‹œ 이벀트 처리λ₯Ό μœ„ν•œ λ©”μ†Œλ“œλ₯Ό onCreate λ©”μ†Œλ“œμ— μΆ”κ°€ν•΄μ€€λ‹€.
//νšŒμ›κ°€μž… λ²„νŠΌμ΄ ν΄λ¦­λ λ•Œμ˜ μ˜΅μ…˜μ²˜λ¦¬  
mBtnRegister.setOnClickListener(new View.OnClickListener() {  
    @Override  
  public void onClick(View v) {  
        String strEmail = mEtEmail.getText().toString();  
  String strPwd = mEtPwd.getText().toString();  
  
  //μ•„λ¬΄λŸ° 정보가 μž…λ ₯λ˜μ§€ μ•Šμ€ μƒνƒœμ—μ„œ λ²„νŠΌ 클릭 μ‹œ 였λ₯˜κ°€ λœ¨λŠ” 것을 방지  
  if(strEmail.getBytes().length <=0 || strPwd.getBytes().length <=0){  
            Toast.makeText(RegisterActivity.this ,"κ°€μž…μ •λ³΄λ₯Ό μž…λ ₯ν•˜μ„Έμš”.", Toast.LENGTH_SHORT).show();  
  }else{  
  
        //FirebaseAuth 진행  
  mFirebaseAuth.createUserWithEmailAndPassword(strEmail, strPwd).addOnCompleteListener(RegisterActivity.this, new OnCompleteListener<AuthResult>() {  
            @Override  
  public void onComplete(@NotNull Task<AuthResult> task) {  
                //νšŒμ›κ°€μž…μ΄ μ΄λ£¨μ–΄μ‘Œμ„λ•Œ 처리  
  if(task.isSuccessful()){  
                    FirebaseUser firebaseUser = mFirebaseAuth.getCurrentUser();  
  UserAccount account = new UserAccount();  
  account.setIdToken(firebaseUser.getUid());  
  account.setEmailId(firebaseUser.getEmail());  
  account.setPassword(strPwd);  
  
  //setValue λŠ” database에 μ‚½μž…ν•˜λŠ” ν–‰μœ„  
  mDatabaseRef.child("UserAccount").child(firebaseUser.getUid()).setValue(account);  
  
  Toast.makeText(RegisterActivity.this, "νšŒμ›κ°€μž…μ— μ„±κ³΅ν•˜μ…¨μŠ΅λ‹ˆλ‹€.", Toast.LENGTH_SHORT).show();  
  
  Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);  
  startActivity(intent);  
  } else {  
                    Toast.makeText(RegisterActivity.this, "νšŒμ›κ°€μž…μ— μ‹€νŒ¨ν•˜μ…¨μŠ΅λ‹ˆλ‹€.", Toast.LENGTH_SHORT).show();  
  }  
            }  
        });}  
    }  
});

3. 둜그인 ν™”λ©΄ ꡬ성

  1. LoginActivity λΌλŠ” μ΄λ¦„μ˜ empty activity λ₯Ό 생성해쀀 ν›„ activity_login.xml μ—μ„œ 이메일과 λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•  수 μžˆλŠ” EditText 와 둜그인 λ²„νŠΌκ³Ό νšŒμ›κ°€μž… ν™”λ©΄μœΌλ‘œ λ„˜κ²¨μ£ΌλŠ” λ²„νŠΌμ„ κ΅¬ν˜„ν•΄μ€€λ‹€.
<?xml version="1.0" encoding="utf-8"?>  
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  xmlns:app="http://schemas.android.com/apk/res-auto"  
  xmlns:tools="http://schemas.android.com/tools"  
  android:layout_width="match_parent"  
  android:layout_height="match_parent"  
  tools:context=".LoginActivity">  
  
 <EditText  android:id="@+id/et_email"  
  android:layout_width="300dp"  
  android:layout_height="40dp"  
  android:layout_marginTop="200dp"  
  android:ems="10"  
  android:hint="이메일을 μž…λ ₯ν•˜μ„Έμš”"  
  android:inputType="textEmailAddress"  
  app:layout_constraintEnd_toEndOf="parent"  
  app:layout_constraintStart_toStartOf="parent"  
  app:layout_constraintTop_toTopOf="parent" />  
  
 <EditText  android:id="@+id/et_pwd"  
  android:layout_width="300dp"  
  android:layout_height="40dp"  
  android:layout_marginTop="32dp"  
  android:ems="10"  
  android:hint="λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•˜μ„Έμš”"  
  android:inputType="textPassword"  
  app:layout_constraintEnd_toEndOf="parent"  
  app:layout_constraintHorizontal_bias="0.498"  
  app:layout_constraintStart_toStartOf="parent"  
  app:layout_constraintTop_toBottomOf="@+id/et_email" />  
  
 <Button  android:id="@+id/btn_login"  
  android:layout_width="0dp"  
  android:layout_height="wrap_content"  
  android:layout_marginTop="24dp"  
  android:layout_marginEnd="150dp"  
  android:text="둜그인"  
  app:layout_constraintEnd_toEndOf="@+id/et_pwd"  
  app:layout_constraintStart_toStartOf="@+id/et_pwd"  
  app:layout_constraintTop_toBottomOf="@+id/et_pwd" />  
  
 <Button  android:id="@+id/btn_register"  
  android:layout_width="0dp"  
  android:layout_height="wrap_content"  
  android:layout_marginStart="150dp"  
  android:layout_marginTop="24dp"  
  android:text="νšŒμ›κ°€μž…"  
  app:layout_constraintEnd_toEndOf="@+id/et_pwd"  
  app:layout_constraintStart_toStartOf="@+id/et_pwd"  
  app:layout_constraintTop_toBottomOf="@+id/et_pwd" />  
</androidx.constraintlayout.widget.ConstraintLayout>
  1. LoginActivity 에 둜그인과 κ΄€λ ¨ν•œ Firebase 인증처리, 둜그인 λ²„νŠΌ ν΄λ¦­μ‹œ MainActivity ν™”λ©΄μœΌλ‘œ λ„˜κ²¨μ£ΌλŠ” μ˜΅μ…˜ μ²˜λ¦¬μ™€ νšŒμ›κ°€μž… λ²„νŠΌ 클릭 μ‹œ νšŒμ›κ°€μž… ν™”λ©΄μœΌλ‘œ λ„˜κ²¨μ£ΌλŠ” μ˜΅μ…˜ 처리 λ“±μ˜ μ½”λ“œλ₯Ό μΆ”κ°€ν•΄μ€€λ‹€.
  
    private FirebaseAuth mFirebaseAuth; //Firebase 인증처리  
  private DatabaseReference mDatabaseRef; //μ‹€μ‹œκ°„ λ°μ΄ν„°λ² μ΄μŠ€ -> μ„œλ²„μ— μ—°λ™μ‹œν‚¬μˆ˜μžˆλŠ” 객체  
  private EditText mEtEmail, mEtPwd; //둜그인 μž…λ ₯ν•„λ“œ  
  EditText editText1, editText2;  
  
  
  
  @Override  
  protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
  setContentView(R.layout.activity_login);  
  
  
  mFirebaseAuth = FirebaseAuth.getInstance(); //firebase μ΄μš©μ€€λΉ„ 끝  
  mDatabaseRef = FirebaseDatabase.getInstance().getReference("mapbox");  
  
  mEtEmail = findViewById(R.id.et_email);  
  mEtPwd = findViewById(R.id.et_pwd);  
  
  Button btn_login = findViewById(R.id.btn_login);  
  btn_login.setOnClickListener(new View.OnClickListener() {  
            @Override  
  public void onClick(View v) {  
  
                //둜그인 μš”μ²­  
  String strEmail = mEtEmail.getText().toString();  
  String strPwd = mEtPwd.getText().toString();  
  
 if(strEmail.getBytes().length <= 0 || strPwd.getBytes().length <= 0){  
                    Toast.makeText(LoginActivity.this, "둜그인 정보λ₯Ό μž…λ ₯ν•˜μ„Έμš”", Toast.LENGTH_SHORT).show();  
  }else {  
  
                mFirebaseAuth.signInWithEmailAndPassword(strEmail, strPwd).addOnCompleteListener(LoginActivity.this, new OnCompleteListener<AuthResult>() {  
                    @Override  
  public void onComplete( @NotNull Task<AuthResult> task) {  
                        if(task.isSuccessful()){  
                            //둜그인 μ„±κ³΅μ‹œ MainAcitivity둜 μ—°κ²°  
  Intent intent = new Intent(LoginActivity.this, MainActivity.class);  
  startActivity(intent);  
  //finish(); //ν˜„μž¬μ•‘ν‹°λΉ„ν‹° 파괴  
  } else {  
                            Toast.makeText(LoginActivity.this , "둜그인 μ‹€νŒ¨", Toast.LENGTH_SHORT).show();  
  }  
                    }  
                });}  
            }  
        });  
  
  Button btn_register = findViewById(R.id.btn_register);  
  btn_register.setOnClickListener(new View.OnClickListener() {  
            @Override  
  public void onClick(View v) {  
                //νšŒμ›κ°€μž… λ²„νŠΌμ„ λˆŒλ €μ„ λ•Œμ˜ 처리 -> νšŒμ›κ°€μž… 창으둜 이동  
  Intent intent = new Intent(LoginActivity.this, RegisterActivity.class);  
  startActivity(intent);  
  }  
        });  
  }  
}
  1. 둜그인 μ™„λ£Œ ν›„ λ’€λ‘œκ°€κΈ° λ²„νŠΌμ„ λˆŒλ €μ„ λ•Œ λ‹€μ‹œ 둜그인 ν™”λ©΄μœΌλ‘œ λ„˜μ–΄κ°€λŠ” 것을 막아주기 μœ„ν•΄ MainActivity 에 λ‹€μŒκ³Ό 같은 μ½”λ“œλ₯Ό μΆ”κ°€ν•˜μ—¬ μ€€λ‹€.
//λ’€λ‘œκ°€κΈ° λ²„νŠΌμ„ λ§‰μ•„μ„œ 둜그인 ν™”λ©΄μœΌλ‘œ λ„˜μ–΄κ°€λŠ” 였λ₯˜λ₯Ό ν•΄κ²°  
@Override  
public void onBackPressed(){  
    //super.onBackPressed();  
}
  1. μ•± μ‹€ν–‰μ‹œ LoginActivity κ°€ κ°€μž₯ λ¨Όμ € μ‹€ν–‰λ˜λ„λ‘ ν•˜μ—¬ 둜그인 화면이 κ°€μž₯ λ¨Όμ € 화면에 λ„μ›Œμ§€λ„λ‘ μ„€μ •ν•˜κΈ° μœ„ν•΄ manifests 의 intent-filter λ₯Ό λ‹€μŒκ³Ό 같이 LoginActivity μ•žμœΌλ‘œ μ—°κ²°μ‹œμΌœμ€€λ‹€.
<activity android:name=".LoginActivity"  
  android:theme="@style/Theme.AppCompat">  
 <intent-filter> <action android:name="android.intent.action.MAIN" />  
  
 <category android:name="android.intent.category.LAUNCHER" />  
 </intent-filter></activity>
  1. MainActivity ν™”λ©΄μ˜ μ˜΅μ…˜λ©”λ‰΄μ—μ„œ λ‘œκ·Έμ•„μ›ƒ λ²„νŠΌ 클릭 μ‹œ 둜그인 ν™”λ©΄μœΌλ‘œ λ˜λŒμ•„ κ°€κ²Œ ν•΄μ£ΌκΈ° μœ„ν•΄ menuoptions.xml κ³Ό MainActivity 에 λ‹€μŒκ³Ό 같이 μ½”λ“œλ₯Ό μΆ”κ°€ν•΄μ€€λ‹€.
menuoptions.xml
<item  
  android:title="λ‘œκ·Έμ•„μ›ƒ"  
  android:id="@+id/logout"/>
MainActivity
  
//μ•± μƒνƒœλ°” 메뉴λ₯Ό λ©”μΈμ΄λ²€νŠΈμ— μ—°λ™μ‹œμΌœμ£ΌλŠ” λ©”μ†Œλ“œ  
public boolean onCreateOptionsMenu(Menu menu){  
    getMenuInflater().inflate(R.menu.menuoptions, menu);  
 return true;}  
  
//클릭 이벀트 처리  
//메뉴 ν΄λ¦­μ‹œ μ„ νƒν•œ 메뉴λ₯Ό ν˜ΈμΆœν•˜κ²Œ ν•˜λŠ” λ©”μ†Œλ“œ  
public boolean onOptionsItemSelected(MenuItem item){  
    switch (item.getItemId()){  
        case R.id.logout:  
  
            mFirebaseAuth.signOut();  
  Intent intent = new Intent(MainActivity.this, LoginActivity.class);  
  startActivity(intent);  
  Toast.makeText(MainActivity.this,"λ‘œκ·Έμ•„μ›ƒ λ˜μ—ˆμŠ΅λ‹ˆλ‹€", Toast.LENGTH_SHORT).show();  
  
  }  
    return false;  
}

4. μ‚¬μš©μž 정보 λͺ¨λΈ 클래슀

  1. UserAccount λΌλŠ” μ΄λ¦„μ˜ μ‚¬μš©μž 계정 정보λ₯Ό κ°€μ Έμ˜€λŠ” 클래슀 생성 ν›„ getter 와 setter λ₯Ό μ΄μš©ν•˜μ—¬ λ‹€μŒκ³Ό 같이 μ½”λ“œλ₯Ό μž‘μ„±ν•œλ‹€.
package com.example.mapbox;  
  
// νšŒμ›κ°€μž… μ‚¬μš©μž 계정 정보 λͺ¨λΈ 클래슀  
public class UserAccount {  
  
    private String idToken; //Firebase Uid(고유 토큰 정보)  
  private String emailId; // 이메일아이디  
  private String password; // λΉ„λ°€λ²ˆν˜Έ  
  
  //firebase λŠ” 빈 μƒμ„±μžλ₯Ό λ§Œλ“€μ–΄μ€˜μ•Ό 였λ₯˜κ°€ λ‚˜μ§€ μ•ŠλŠ”λ‹€.  
  public UserAccount() {  
    }  
  
    public String getIdToken() {  
        return idToken;  
  }  
  
    public void setIdToken(String idToken) {  
        this.idToken = idToken;  
  }  
  
    public String getEmailId() {  
        return emailId;  
  }  
  
    public void setEmailId(String emailId) {  
        this.emailId = emailId;  
  }  
  
    public String getPassword() {  
        return password;  
  }  
  
    public void setPassword(String password) {  
        this.password = password;  
  }  
}

MAPBOX

λ§΅λ°•μŠ€λŠ” 3차원 동적 지도 μ›Ήμ„œλΉ„μŠ€ κ°œλ°œμ„ μ§€μ›ν•˜κ³  λ§žμΆ€ν˜• λ””μžμΈ 맡을 μœ„ν•œ μ˜€ν”ˆ μ†ŒμŠ€ 맀핑 ν”Œλž«νΌμ΄λ‹€. λ§΅λ°•μŠ€λ₯Ό μ΄μš©ν•΄ 동적지도, 3차원 지도, λ„€λΉ„κ²Œμ΄μ…˜, μ¦κ°•ν˜„μ‹€ λ‹€μ–‘ν•œ 것을 λ§Œλ“€ 수 μžˆλ‹€.

MAPBOX λ„€λΉ„κ²Œμ΄μ…˜ SDK μ„€μΉ˜λ°©λ²•

λ§΅λ°•μŠ€λ₯Ό ν™œμš©ν•˜μ—¬ λ„€λΉ„κ²Œμ΄μ…˜ κΈ°λŠ₯을 κ΅¬ν˜„ν•˜κΈ° μœ„ν•΄μ„œλŠ” μ•ˆλ“œλ‘œμ΄λ“œ μŠ€νŠœλ””μ˜€μ— λ§΅λ°•μŠ€ SDK 및 λ§΅λ°•μŠ€ λ„€λΉ„κ²Œμ΄μ…˜ SDK 두가지λ₯Ό μ„€μΉ˜ν•΄μ•Όν•œλ‹€.

μ°Έκ³ : https://docs.mapbox.com/help/tutorials/android-navigation-sdk/ https://docs.mapbox.com/android/maps/guides/install/ (λ§΅λ°•μŠ€ SDK μ„€μΉ˜ 및 λ§΅λ°•μŠ€ λ„€λΉ„κ²Œμ΄μ…˜ νŠœν† λ¦¬μ–Ό)

  1. λ‹€μŒκ³Ό 같이 MAPBOX Account νŽ˜μ΄μ§€μ— μ ‘μ†ν•˜μ—¬ 둜그인 ν›„ λ‹€μŒκ³Ό 같이 ACCESS 토큰을 λ³΅μ‚¬ν•œλ‹€. 캑처

  2. λͺ¨λ“ˆμˆ˜μ€€μ˜ build.gradle 의 dependencies 에 λ‹€μŒκ³Ό 같이 μ΅œμ‹ λ²„μ „μ˜ SDK λ‘κ°œλ₯Ό μΆ”κ°€ν•΄μ€€λ‹€.

implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.6.1'
implementation 'com.mapbox.mapboxsdk:mapbox-android-navigation-ui:0.42.6'
  1. ν”„λ‘œμ νŠΈ μˆ˜μ€€μ˜ build.gradle 의 repositories 에 λ‹€μŒμ„ μΆ”κ°€ν•΄μ€€λ‹€.
maven { url 'https://mapbox.bintray.com/mapbox' }
  1. string.xml 에 λ³΅μ‚¬ν•œ access 토큰을 λΆ™μ—¬λ„£λŠ”λ‹€.
<string name="mapbox_access_token" translatable="false">MAMBOX_ACCESS_TOKEN</string>
  1. Manifest.xml 에 λ§΅λ°•μŠ€ κ΄€λ ¨ κΆŒν•œμ„ μΆ”κ°€ν•΄μ£ΌκΈ° μœ„ν•΄μ„œ λ‹€μŒμ„ μΆ”κ°€ν•΄μ€€λ‹€.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ΄ μ΄ˆκΈ°ν™” 될 λ•Œ μ‚¬μš©λ  지도 μŠ€νƒ€μΌμ„ ν¬ν•¨ν•˜μ—¬ MapView 의 속성과 λ„€λΉ„κ²Œμ΄μ…˜ μŠ€νƒ€νŠΈ λ²„νŠΌμ„ μΆ”κ°€ν•΄μ£ΌκΈ° μœ„ν•΄ activity_main.xml 에 λ‹€μŒμ„ μΆ”κ°€ν•΄μ€€λ‹€.
<com.mapbox.mapboxsdk.maps.MapView  
  android:id="@+id/mapView"  
  android:layout_width="match_parent"  
  android:layout_height="match_parent"  
  mapbox:mapbox_cameraTargetLat="38.9098"  
  mapbox:mapbox_cameraTargetLng="-77.0295"  
  mapbox:mapbox_cameraZoom="15.5" />  
  
  
//2dλ„€λΉ„κ²Œμ΄μ…˜ μŠ€νƒ€νŠΈ λ²„νŠΌ  
<Button  
  android:id="@+id/startButton"  
  android:layout_width="50dp"  
  android:layout_height="wrap_content"  
  android:layout_marginRight="16dp"  
  android:layout_marginBottom="20dp"  
  android:background="@color/mapboxGrayLight"  
  android:enabled="false"  
  android:text="2D"  
  android:textColor="@color/mapboxWhite"  
  mapbox:layout_constraintRight_toRightOf="parent"  
  mapbox:layout_constraintBottom_toBottomOf="parent" />
  1. λ§΅λ°•μŠ€ 지도λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄ MainActivity 에 λ‹€μŒμ„ μΆ”κ°€ν•΄μ€€λ‹€.
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;

import com.mapbox.geojson.Feature;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, MapboxMap.OnMapClickListener, PermissionsListener {

  private MapView mapView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Mapbox.getInstance(this, getString(R.string.access_token));
    setContentView(R.layout.activity_main);
    mapView = findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);
    mapView.getMapAsync(new OnMapReadyCallback() {
      @Override
      public void onMapReady(@NonNull final MapboxMap mapboxMap) {

        mapboxMap.setStyle(Style.LIGHT, new Style.OnStyleLoaded() {
          @Override
          public void onStyleLoaded(@NonNull Style style) {
              // Map is set up and the style has loaded. Now you can add data or make other map adjustments
          }
        });
      }
    });
  }

  // Add the mapView's own lifecycle methods to the activity's lifecycle methods
  @Override
  public void onStart() {
    super.onStart();
    mapView.onStart();
  }

  @Override
  public void onResume() {
    super.onResume();
    mapView.onResume();
  }

  @Override
  public void onPause() {
    super.onPause();
    mapView.onPause();
  }

  @Override
  public void onStop() {
    super.onStop();
    mapView.onStop();
  }

  @Override
  public void onLowMemory() {
    super.onLowMemory();
    mapView.onLowMemory();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapView.onSaveInstanceState(outState);
  }

getRoute λ©”μ†Œλ“œ

getRoute λŠ” μ‚¬μš©μžμ˜ μœ„μΉ˜μ™€ λͺ©μ μ§€ μ‚¬μ΄μ˜ μ’Œν‘œλ₯Ό κ΅¬ν•΄μ£ΌλŠ” λ©”μ†Œλ“œμ΄λ‹€. μ•„λž˜λŠ” 도보 μ „μš© κΈΈμ°ΎκΈ° λ©”μ†Œλ“œμ΄λ‹€. μ°¨λŸ‰μš© 길찾기둜 섀정을 λ°”κΎΈλ €λ©΄ .profile(DirectionsCriteria.PROFILE_WALKING) 이 뢀뢄을 μ§€μ›Œμ£Όκ±°λ‚˜ μ£Όμ„μ²˜λ¦¬ν•œλ‹€.

//λ‚΄ μœ„μΉ˜μ™€ λͺ©μ μ§€ μ‚¬μ΄μ˜ 루트λ₯Ό κ΅¬ν•΄μ£ΌλŠ” ν•¨μˆ˜  
//ν˜„μž¬ 도보 길찾기둜 μ„€μ •ν•΄λ†“μ€κ±°μž„  
private void getRoute(Point origin, Point destination) {  
    NavigationRoute.builder(this)  
            .accessToken(Mapbox.getAccessToken())  
            .profile(DirectionsCriteria.PROFILE_WALKING) //도보 κΈΈμ°ΎκΈ° -> μ°¨λŸ‰ κΈΈμ°ΎκΈ°μ‹œ μ£Όμ„μ²˜λ¦¬  
  .origin(origin)  
            .destination(destination)  
            .build()  
            .getRoute(new Callback<DirectionsResponse>() {  
                @Override  
  public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {  
                    // You can get the generic HTTP info about the response  
  Log.d(TAG, "Response code: " + response.code());  
 if (response.body() == null) {  
                        Log.e(TAG, "No routes found, make sure you set the right user and access token.");  
 return;  } else if (response.body().routes().size() < 1) {  
                        Log.e(TAG, "No routes found");  
 return;  }  
  
                    currentRoute = response.body().routes().get(0);  
  
 if (navigationMapRoute != null){  
                        navigationMapRoute.removeRoute();  
  } else {  
                        navigationMapRoute = new NavigationMapRoute(null, mapView, mapboxMap);  
  }  
  
                    navigationMapRoute.addRoute(currentRoute);  
  }  
  
                @Override  
  public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {  
                    Log.e(TAG, "Error: " + throwable.getMessage());  
  }  
            });  
}

λͺ©μ μ§€ μ„€μ • 방법

MAPBOX νŠœν† λ¦¬μ–Όμ€ 맡에 ν΄λ¦­ν•œ 곳의 μ’Œν‘œλ₯Ό λͺ©μ μ§€λ‘œ λ°›μ•„μ˜€κ³  μ‚¬μš©μžμ™€μ˜ 루트λ₯Ό κ΅¬ν•΄μ£ΌλŠ” λ°©μ‹μ΄μ—ˆλ‹€. ν•˜μ§€λ§Œ DK GIUDE λŠ” λ‹¨κ΅­λŒ€ μ „μš© κ°€μ΄λ“œ μ•±μ΄λ―€λ‘œ νŒμ—… 메뉴λ₯Ό ν™œμš©ν•˜μ—¬ μœ„μΉ˜λ₯Ό ν•œμ •ν•˜μ˜€λ‹€.

  1. GeoPlaner λ₯Ό ν™œμš©ν•˜μ—¬ λ‚΄κ°€ μ›ν•˜λŠ” 곳의 μ’Œν‘œλ₯Ό 맡클릭을 톡해 보닀 μ„Έμ„Έν•˜κ²Œ μ–»μ–΄ 올 수 μžˆλ‹€. 캑처1

  2. 각 건물에 μ–»μ–΄μ˜¨ μ’Œν‘œλ₯Ό 각각 직접 μž…λ ₯으둜 λ„£μ–΄μ€€λ‹€. 각 if λ¬Έμ—λŠ” 건물에 ν•΄λ‹Ήν•˜λŠ” μ’Œν‘œκ°’μ„ destinationPoint 둜 전달을 ν•˜μ˜€κ³  getRoute λ©”μ†Œλ“œλ₯Ό ν™œμš©ν•˜μ—¬ μ‚¬μš©μžμ˜ μœ„μΉ˜λ₯Ό λ‚˜νƒ€λ‚΄λŠ” originPoint 와 destinationPoint μ‚¬μ΄μ˜ λ„λ³΄κ²½λ‘œλ₯Ό ꡬ해쀀닀. μ•„λž˜ μ½”λ“œλŠ” λ‹¨κ΅­λŒ€ν•™κ΅ μ£½μ „μΊ νΌμŠ€μ˜ 건물 μ€‘μ‹¬μœΌλ‘œ 코딩을 ν•œκ²ƒμ΄λ‹€.

//button1 은 λͺ©μ μ§€μ„€μ • λ²„νŠΌ  
button1.setOnClickListener(new View.OnClickListener() {  
    @Override  
  public void onClick(final View v) {  
        final PopupMenu popupMenu = new PopupMenu(getApplicationContext(), v);  
  getMenuInflater().inflate(R.menu.popup, popupMenu.getMenu());  
  popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {  
            @Override  
  public boolean onMenuItemClick(MenuItem item) {  
                //제 1곡학관  
  if (item.getItemId() == R.id.action_menu1){  
                    destinationPoint = Point.fromLngLat(127.12584,37.32119);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //제 2곡학관  
  else if (item.getItemId() == R.id.action_menu2){  
                    destinationPoint = Point.fromLngLat(127.12629,37.32080);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //제 3곡학관  
  else if (item.getItemId() == R.id.action_menu3){  
                    destinationPoint = Point.fromLngLat(127.12676,37.32043);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //μ‚¬νšŒκ³Όν•™κ΄€  
  else if (item.getItemId() == R.id.action_menu4){  
                    destinationPoint = Point.fromLngLat(127.12564,37.32137);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //μ†Œν”„νŠΈμ›¨μ–΄ ICTκ΄€  
  else if (item.getItemId() == R.id.action_menu5){  
                    destinationPoint = Point.fromLngLat(127.12753,37.32274);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //λ―Έλ””μ–΄μ„Όν„°  
  else if (item.getItemId() == R.id.action_menu6){  
                    destinationPoint = Point.fromLngLat(127.12753,37.32242);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //λ²”μ •κ΄€  
  else if (item.getItemId() == R.id.action_menu7){  
                    destinationPoint = Point.fromLngLat(127.12641,37.32196);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //인문관  
  else if (item.getItemId() == R.id.action_menu8){  
                    destinationPoint = Point.fromLngLat(127.12896,37.32178);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //상경관  
  else if (item.getItemId() == R.id.action_menu9){  
                    destinationPoint = Point.fromLngLat(127.12894,37.32227);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //사범관  
  else if (item.getItemId() == R.id.action_menu10){  
                    destinationPoint = Point.fromLngLat(127.12897,37.32272);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //ν˜œλ‹Ήκ΄€  
  else if (item.getItemId() == R.id.action_menu11){  
                    destinationPoint = Point.fromLngLat(127.12827,37.32047);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //ν‡΄κ³„κΈ°λ…μ€‘μ•™λ„μ„œκ΄€  
  else if (item.getItemId() == R.id.action_menu12){  
                    destinationPoint = Point.fromLngLat(127.12746,37.32116);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //법학관, λŒ€ν•™μ›λ™  
  else if (item.getItemId() == R.id.action_menu13){  
                    destinationPoint = Point.fromLngLat(127.12921,37.32107);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //κ΅­μ œκ΄€  
  else if (item.getItemId() == R.id.action_menu14){  
                    destinationPoint = Point.fromLngLat(127.12717,37.31919);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //μ’…ν•©μ‹€ν—˜λ™  
  else if (item.getItemId() == R.id.action_menu15){  
                    destinationPoint = Point.fromLngLat(127.12577,37.32014);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //곰상  
  else if (item.getItemId() == R.id.action_menu16){  
                    destinationPoint = Point.fromLngLat(127.12892,37.31996);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //μ •λ¬Έ  
  else if (item.getItemId() == R.id.action_menu17){  
                    destinationPoint = Point.fromLngLat(127.12547,37.32346);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //μ²΄μœ‘κ΄€  
  else if (item.getItemId() == R.id.action_menu18){  
                    destinationPoint = Point.fromLngLat(127.13213,37.31936);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
                //λŒ€μš΄λ™μž₯  
  else if (item.getItemId() == R.id.action_menu19){  
                    destinationPoint = Point.fromLngLat(127.13300,37.32080);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //λ¬΄μš©κ΄€  
  else if (item.getItemId() == R.id.action_menu20){  
                    destinationPoint = Point.fromLngLat(127.12724,37.31585);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //진리관  
  else if (item.getItemId() == R.id.action_menu21){  
                    destinationPoint = Point.fromLngLat(127.12682,37.31479);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //웅비홀  
  else if (item.getItemId() == R.id.action_menu22){  
                    destinationPoint = Point.fromLngLat(127.12698,37.31567);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //μ§‘ν˜„μž¬  
  else if (item.getItemId() == R.id.action_menu23){  
                    destinationPoint = Point.fromLngLat(127.12695,37.31667);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //μ£½μ „μΉ˜κ³Όλ³‘μ›  
  else if (item.getItemId() == R.id.action_menu24){  
                    destinationPoint = Point.fromLngLat(127.12513,37.32187);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //λ…Έμ²œλ§ˆλ‹Ή, ν’‹μ‚΄μž₯  
  else if (item.getItemId() == R.id.action_menu25){  
                    destinationPoint = Point.fromLngLat(127.12724,37.31988);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //μŒμ•…κ΄€  
  else if (item.getItemId() == R.id.action_menu26){  
                    destinationPoint = Point.fromLngLat(127.12935,37.31918);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //λ―Έμˆ κ΄€  
  else if (item.getItemId() == R.id.action_menu27){  
                    destinationPoint = Point.fromLngLat(127.13088,37.31983);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
  
                //폭포곡원  
  else if (item.getItemId() == R.id.action_menu28){  
                    destinationPoint = Point.fromLngLat(127.13065,37.32082);  
  originPoint = Point.fromLngLat(Lo,La);  
  getRoute(originPoint, destinationPoint);  
  button.setEnabled(true);  
  button.setBackgroundResource(R.color.mapboxBlue);  
  }  
               
  return false;  
  }  
        });  
  
  //νŒμ—…λ©”λ‰΄λ₯Ό 보이게 ν•˜λŠ”κ±°  
  popupMenu.show();  
  }  
}

μ‚¬μš©μž μœ„μΉ˜

GPS λ₯Ό ν™œμš©ν•˜μ—¬ λ‚˜μ˜ μœ„μΉ˜λ₯Ό 맡에 ν‘œμ‹œν•΄μ£Όκ³  originPoint 에 λ‚΄ ν˜„μž¬ μœ„μΉ˜μ˜ μœ„λ„, 경도 값을 μ „λ‹¬ν•΄μ£ΌλŠ” 방식을 μ΄μš©ν•˜μ˜€λ‹€.

  1. μ‚¬μš©μžμ˜ μœ„μΉ˜λ₯Ό 지도에 ν‘œμ‹œ ν•˜κΈ° μœ„ν•œ λ©”μ†Œλ“œ
//User 의 μœ„μΉ˜λ₯Ό λ‚˜νƒ€λ‚΄μ£ΌλŠ” λ©”μ†Œλ“œ  
@SuppressWarnings( {"MissingPermission"})  
private void enableLocationComponent(@NonNull Style loadedMapStyle) {  
    // Check if permissions are enabled and if not request  
  if (PermissionsManager.areLocationPermissionsGranted(this)) {  
        // Activate the MapboxMap LocationComponent to show user location  
 // Adding in LocationComponentOptions is also an optional parameter // Set the LocationComponent activation options  
  locationComponent = mapboxMap.getLocationComponent();  
  
  locationComponent.activateLocationComponent(LocationComponentActivationOptions.builder(this, loadedMapStyle).build());  
  
  locationComponent.setLocationComponentEnabled(true);  
  // Set the component's camera mode  
  locationComponent.setCameraMode(CameraMode.TRACKING);  
  
  locationComponent.setRenderMode(RenderMode.COMPASS);  
  
  initLocationEngine();  
  } else {  
        permissionsManager = new PermissionsManager(this);  
  permissionsManager.requestLocationPermissions(this);  
  }  
}  
  
@SuppressLint("MissingPermission")  
private void initLocationEngine() {  
    Log.e(TAG,"initLocationEngine μ‹€ν–‰");  
  locationEngine = LocationEngineProvider.getBestLocationEngine(this);  
  LocationEngineRequest request = new LocationEngineRequest.Builder(DEFAULT_INTERVAL_IN_MILLISECONDS)  
            .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)  
            .setMaxWaitTime(DEFAULT_MAX_WAIT_TIME).build();  
  locationEngine.requestLocationUpdates(request, callback, getMainLooper());  
  locationEngine.getLastLocation(callback);  
}  
  
@Override  
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {  
    permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);  
}  
  
@Override  
public void onExplanationNeeded(List<String> permissionsToExplain) {  
    Toast.makeText(this, R.string.user_location_permission_explanation, Toast.LENGTH_LONG).show();  
}  
  
@Override  
public void onPermissionResult(boolean granted) {  
    if (granted) {  
        enableLocationComponent(mapboxMap.getStyle());  
  } else {  
        Toast.makeText(this, R.string.user_location_permission_not_granted, Toast.LENGTH_LONG).show();  
  finish();  
  }  
}
  1. μ‚¬μš©μžμ˜ ν˜„μž¬μœ„μΉ˜ μœ„λ„, 경도값을 originPoint 에 μ „λ‹¬ν•΄μ£ΌλŠ” λ³€μˆ˜ Lo, La 에 λ„£μ–΄μ£ΌκΈ° μœ„ν•œ 클래슀 Lo, La μ—λŠ” μ‚¬μš©μžμ˜ μœ„λ„, 경도 값이 각각 λ“€μ–΄κ°€ μžˆλ‹€.
class MainActivityLocationCallback implements LocationEngineCallback<LocationEngineResult> {  
    private final WeakReference<MainActivity> activityWeakReference;  
  MainActivityLocationCallback(MainActivity activity) {  
        this.activityWeakReference = new WeakReference<>(activity);  
  }  
    /**  
 * The LocationEngineCallback interface's method which fires when the device's location has changed. * @param result the LocationEngineResult object which has the last known location within it.  
 */  @Override  
  public void onSuccess(LocationEngineResult result) {  
        Log.e(TAG,"onSuccess μ‹€ν–‰");  
  MainActivity activity = activityWeakReference.get();  
 if (activity != null) {  
            Location location = result.getLastLocation();  
 if (location == null) {  
                return;  
  }  
            // Create a Toast which displays the new location's coordinates  
 //λ‚˜μ˜ μœ„μΉ˜λ₯Ό λ°›μ•„μ™€μ„œ La, Lo 에 λ„£μŒ  
  La = result.getLastLocation().getLatitude();  
  Lo = result.getLastLocation().getLongitude();  
  
  // Pass the new location to the Maps SDK's LocationComponent  
  if (activity.mapboxMap != null && result.getLastLocation() != null) {  
                activity.mapboxMap.getLocationComponent().forceLocationUpdate(result.getLastLocation());  
  }  
        }  
    }  
  
    /**  
 * The LocationEngineCallback interface's method which fires when the device's location can not be captured * * @param exception the exception message  
 */  @Override  
  public void onFailure(@NonNull Exception exception) {  
        Log.e("LocationChangeActivity", exception.getLocalizedMessage());  
  MainActivity activity = activityWeakReference.get();  
 if (activity != null) {  
            Toast.makeText(activity, exception.getLocalizedMessage(),  
  Toast.LENGTH_SHORT).show();  
  }  
    }  
}
  1. onstyleLoaded λ©”μ†Œλ“œμ— λ‹€μŒμ„ μΆ”κ°€ν•˜μ—¬ 맡이 λ‘œλ“œλ˜λ©΄ μ‚¬μš©μžμ˜ μœ„μΉ˜κ°€ 맡에 ν‘œμ‹œλ˜λ„λ‘ ν•œλ‹€.
enableLocationComponent(style);


#κ°œμ„ λ°©μ•ˆ

  1. νšŒμ›μ •λ³΄λ₯Ό μ›Ή ν˜ΈμŠ€νŒ…μ„ 톡해 κ΄€λ¦¬ν•˜λ©΄ 효율적으둜 관리λ₯Ό ν•  수 μžˆμ„ 것 κ°™μŒ.
  2. λͺ©μ μ§€ μœ„μΉ˜μ˜ μœ„λ„, 경도 μ’Œν‘œλ₯Ό λ°μ΄ν„°λ² μ΄μŠ€λ₯Ό 톡해 κ΄€λ¦¬ν•˜λ©΄ λ”μš± νŽΈν•  것 κ°™μŒ