오늘은 데이터 입력 화면을 하나 만들어 테스트 해보겠습니다.

입력 폼을 두개 만들어 비교를 하고 모양은 아래와 같습니다.


angular material form

 


form을 두개 만들고 데이터를 입력하여 어떻게 처리 되는지 보려고 합니다.


상단 폼은 일반적인 형태의 폼 테그입니다.


두번째는 Angular Material을 사용한 입력 폼 입니다.

 

작업할 파일은 다음 그림과 같습니다.



위에 2개의 파일이 주요 작업 대상이고 나머지는 그냥 설정 파일들 입니다.


작업 순서


이전에 했던  component 추가 파일을 가지고 작업합니다.

[angular] component 추가 방법


1. 먼저 기존 화면을 수정합니다.  기존화면은 Angular 마크가 커다랗게 나왔는데 모두 주석처리 합니다.

2. css 파일 생성

3. html 파일에 form 2개 추가

4. modulematerial 관련 import

5. 변수 및 버튼 클릭 이벤트 함수 생성

6. 테마 추가

7. 화면 테스트


이런식으로 진행 됩니다.


1. 메인 화면 주석 처리


/src/app/app.component.html


파일을 열고 모두 주석 처리를 하여 새로 추가한

/src/app/company-vision/company-vision.component.html 화면만 나오도록 합니다.


 

2. css 파일 생성


company-vision 관련 화면에만 나오도록 하려면 company-vision.component.css 여기에 추가하면 됩니다.

저는 전체에 적용하는 것으로 작업 합니다.



2.1 폴더 및 파일 생성


먼저 css 폴더를 생성 합니다.


assets에 마우스를 놓고 우측 버튼을 클릭해서 New를 선택하고 Folder를 선택합니다.


 

폴더 생성 팝업 창이 나타납니다.


Folder name:css를 입력 합니다.

 


만드는 김에 혹시나 해서 이미지 폴더도 만들었습니다.



Folder name: images를 입력 합니다.

 

생성된 css 폴더에 css 파일을 하나 생성 합니다.

 

css 폴더에 마우스를 놓고 우측 버튼 > New 선택 > Other… 선택



 

창이 열리면 Web찾아서 펼칩니다.


CSS File을 선택하고 하단의 Next 버튼을 클릭 합니다.



 파일 이름을 저는 form.css로 정했습니다. 각자 편한 이름으로 기입하시고 [Finish] 버튼을 클릭 합니다.



form.css 파일이 생성 되었습니다.


필요한 내용을 적어줍니다. 소스는 하단에 추가 하겠습니다.




2.2 CSS 반영


새로 추가한 form.css를 반영해보겠습니다.


/app/company-vision/company-vision.component.ts


파일을 열고 기존 css 파일은 주석처리 또는 삭제하고 신규 파일의 path도 같이 추가를 하면 되는데

css 파일의 path 잡기가 어렵지 않습니다.

자동 완성 기능이 있어서 아주 쉽게 처리 할 수 있습니다.



pathfile도 자동으로 완성 기능이 적용 됩니다.


styleUrls: ['../../assets/css/form.css']



3. html 파일에 form 2개 추가


이제 화면 작업을 진행 합니다.


/src/app/company-vision/company-vision.component.html


파일을 열고 열심히 코딩 합니다.


3.1 일반 형태의 form

<form>
    <h3>Input Data</h3>

    <div>
        <label for="vision1">Vision :</label>
        <input name="vision1" #vision1> 
    </div>
    <div>
        <label for="name1">Name :</label>
        <input name="name1" #name1> 
    </div>
    <div>
        <label for="email1">e-mail :</label>
        <input name="email1" #email1>
    </div>

    <button (click)="addArticle1(vision1, name1, email1.value)">
    Submit
    </button>
</form>
Input Data :  {{name3}} / {{email3}}

 

<input name="vision1" #vision1>

<input name="name1" #name1>

<input name="email1" #email1>

name1email1으로 input을 정의 하였고

 

<button (click)="addArticle1(name1, email1)">

버튼 클릭시 addArticle1() 가 실행되도록 연결하였습니다.

 

Input Data :  {{name3}} / {{email3}}

하단에 입력한 값을 보여주도록 했습니다.



3.2 Material 형태의 form

<div class="divcenter">
 <h3>Input Data2</h3>

<div class="example-container">
    <mat-form-field>
        <input matInput #vision2 placeholder="Vision">
    </mat-form-field>
    <mat-form-field>
        <input matInput #name2 placeholder="Name">
    </mat-form-field>
    <mat-form-field>
        <input matInput #email2 placeholder="e-mail">
    </mat-form-field>
    <div class="example-button-row">
        <button mat-raised-button color="primary"
        (click)="addArticle2(vision2, name2, email2.value)">Submit</button>
    </div>
</div>
</div>

Input Data :  {{name4}} / {{email4}}

 

<input matInput #vision2 placeholder="Vision">

<input matInput #name2 placeholder="Name">

<input matInput #email2 placeholder="e-mail">

 

name2email2으로 input을 정의 하였고

태그들이 mat-으로 시작합니다.

 

<button (click)="addArticle1(vision1, name1, email1.value)">

버튼을 클릭하면 addArticle2() 함수가 실행되도록 하였습니다.

 

입력한 데이터는 화면에서 볼 수 있도록

Input Data :  {{name4}} / {{email4}}

하였고요.



4. modulematerial 관련 import


mat-으로 시작하는 material 태그들이 작동되려면 모듈들을 import 해야 합니다.


/src/app/app.module.ts


파일을 열고 import 해줍니다.


import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { MatFormFieldModule } from '@angular/material/form-field';

import { MatInputModule } from '@angular/material';

import { MatButtonModule } from '@angular/material/button';


import 한다고 적용이 되는게 아니고 반영을 해야 합니다.


imports: [

BrowserModule,

BrowserAnimationsModule,

MatFormFieldModule,

MatInputModule,

MatButtonModule

],


뒤에 공백이 있으면 오류가 발생합니다.

앞에 콤마를 찍어도 오류 표시가 나오니까 형식대로 입력 합니다.



5. 변수 및 버튼 클릭 이벤트 함수 생성


이곳에서 실제 코딩이 진행됩니다.


name3: string;

name4: string;

email3: string;

email4: string;


5.1 일반 폼


일반 폼의 버튼을 선택 했을 때 작동하는 이벤트 함수를 생성합니다.

  addArticle1(vision1: HTMLInputElement, name1: HTMLInputElement, email1: string): boolean {
    alert(`Adding article title: ${name1.value} and link: ${email1}`);
    this.companyVision = vision1.value;
    this.name3 = name1.value;
    this.email3 = email1;
    return false;
 }

화면에서 변수를 보낼 때 일반적으로 보내는 방법과 값만 보내는 방법을 사용 했고


addArticle1(vision1, name1, email1.value)


email1은 값만 보내는 방식입니다.


받는 곳에서도 값만 보낸 경우는 string으로 받습니다.


vision1: HTMLInputElement, name1: HTMLInputElement, email1: string

 

받은 값은 변수에 대입할 때도 다르게 적용 합니다.


this.name3 = name1.value;

this.email3 = email1;

 


5.2 Material


두번째 입력 폼은 Angular Material을 사용해 작업을 했습니다.


  addArticle2(vision2: HTMLInputElement, sample1: HTMLInputElement, sample2: string): boolean {
    alert(`Adding article title: ${sample1.value} and link: ${sample2}`);
    this.companyVision = vision2.value;
    this.name4 = sample1.value;
    this.email4 = sample2;
    return false;
 }

그리고 변수도 수정을 했는데요.

보내준 parameter 명을 다르게 받아왔습니다.

사실 실제 코딩에서는 이렇게 해놓으면 헤깔려서 짜증이 나겠죠.

 

vision2: HTMLInputElement, sample1: HTMLInputElement, sample2: string

 

name2sample1으로 email2sample2로 받아 와서 작업을 하였습니다.

 

코딩도 별로 어려울게 없죠?



6. 테마 추가



글을 입력할 때 기존 글자까 휙 하고 위로 올라가는 기능은 테마가 해주는 건데요.


/src/styles.css


파일에 4개의 Theme중 하나를 적어 줍니다.


@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';


4가지 테마는 다음과 같습니다.


deeppurple-amber.css

indigo-pink.css

pink-bluegrey.css

purple-green.css



7. 화면 테스트



이제 테스트를 해볼까요?



 

프로젝트에 마우스를 대고 우측 버튼 > Run As > Angular Web Application을 선택하면

 


 

이제 첫번째 폼에 입력 테스트를 해봅니다.

 


사장이 돈이 오라고 하네요.




직원은 사장 집에 가라 케라 하는군요.



8. Source Code


복사코딩을 위해 소스를 올립니다.


/myNgProject/src/app/company-vision/company-vision.component.html


<h1>
<p>
  company-vision : {{companyVision}}!!
  
</p>
</h1>


<form>
    <h3>Input Data</h3>

    <div>
        <label for="vision1">Vision :</label>
        <input name="vision1" #vision1> 
    </div>
    <div>
        <label for="name1">Name :</label>
        <input name="name1" #name1> 
    </div>
    <div>
        <label for="email1">e-mail :</label>
        <input name="email1" #email1>
    </div>

    <button (click)="addArticle1(vision1, name1, email1.value)">
    Submit
    </button>
</form>
Input Data :  {{name3}} / {{email3}}

<div class="divcenter">
 <h3>Input Data2</h3>

<div class="example-container">
    <mat-form-field>
        <input matInput #vision2 placeholder="Vision">
    </mat-form-field>
    <mat-form-field>
        <input matInput #name2 placeholder="Name">
    </mat-form-field>
    <mat-form-field>
        <input matInput #email2 placeholder="e-mail">
    </mat-form-field>
    <div class="example-button-row">
        <button mat-raised-button color="primary"
        (click)="addArticle2(vision2, name2, email2.value)">Submit</button>
    </div>
</div>
</div>

Input Data :  {{name4}} / {{email4}}


/myNgProject/src/app/company-vision/company-vision.component.ts


import { Component, OnInit } from '@angular/core';
import { Alert } from 'selenium-webdriver';

@Component({
  selector: 'app-company-vision',
  templateUrl: './company-vision.component.html',
  styleUrls: ['../../assets/css/form.css']
  /*styleUrls: ['./company-vision.component.css'] */
})
export class CompanyVisionComponent implements OnInit {

  companyVision: string;
  name3: string;
  name4: string;
  email3: string;
  email4: string;
  constructor() {
    this.companyVision = 'Good Good!!';
    this.name3 = ' ';
    this.email3 = ' ';
  }

  addArticle1(vision1: HTMLInputElement, name1: HTMLInputElement, email1: string): boolean {
    alert(`Adding article title: ${name1.value} and link: ${email1}`);
    this.companyVision = vision1.value;
    this.name3 = name1.value;
    this.email3 = email1;
    return false;
 }

  addArticle2(vision2: HTMLInputElement, sample1: HTMLInputElement, sample2: string): boolean {
    alert(`Adding article title: ${sample1.value} and link: ${sample2}`);
    this.companyVision = vision2.value;
    this.name4 = sample1.value;
    this.email4 = sample2;
    return false;
 }



  ngOnInit() {
  }

}

/myNgProject/src/app/app.component.html


얘는 전체 주석처리만 했음.


/myNgProject/src/app/app.module.ts


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { CompanyVisionComponent } from './company-vision/company-vision.component';

// Material - animation
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material';
import { MatButtonModule } from '@angular/material/button';

@NgModule({
  declarations: [
    AppComponent,
    CompanyVisionComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MatFormFieldModule,
    MatInputModule,
    MatButtonModule
  ],
  providers: [],
  bootstrap: [AppComponent, CompanyVisionComponent]
})
export class AppModule { }


/myNgProject/src/assets/css/form.css


@charset "UTF-8";

form {
    margin: 0 auto;
    width: 500px;
    padding: 10px;
    border: 1px solid #CCC;
    background-color: #cccccc;
}

form div + div {
    margin-top: 5px;
}

label {
    display: inline-block;
    width: 100px;
    text-align: right;
}

input, textarea {
    width: 300px;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}

textarea {
    vertical-align: top;
    height: 100px;
}

button {
    margin-left: 10em;
}

.example-container {
  display: flex;
  flex-direction: column;
}

.example-container > * {
  width: 100%;
}

.example-button-row button,
.example-button-row a {
  margin-right: 8px;
}

.divcenter {
    margin: 0 auto;
    width: 500px;
}


/myNgProject/src/styles.css


/* You can add global styles to this file, and also import other style files */
@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';

- copy coding -


GPS를 이용하여 속도를 측정 해보기로 했습니다.

고등학교 물리 시간에 속시거(속도는 시간 / 거리)라고 외우도록 해서 아직도 기억을 하고 있는데

그외에도 물가중(물체의 힘은 가속도 x 중력)등 이제는 많이 잊어 버렸네요.

가장 중요한 건 단위를 알면 계산이 가능하다는 사실만 알고 있으라고 해서

대학교 물리, 고체, 유체, 열역학 시간에 도움이 많이 되었는데또 딴데로 가네.

 

사실 GPS로 속도 측정은 별로 쓸말이 없습니다.

GPS 측정 자체에 소도가 들어 있고 측정 시간도 들어 있어서 따로 열심히 계산할 것도 없고

차를 타고 다니며 확인을 하는게 전부입니다.

 


1. Location Class


많은 기능들이 있지만 이곳에서 사용하는 method를 기준으로 몇 개만 소개 합니다.


Type 

 Method

 설명

 float

 distanceTo(Location dest)

 주어진 위치와의 거리 차에 대한 근사치 값(m)

 long

 getTime()

 1970.1.1 기준 밀리세컨드

 float

 getSpeed()

 속도(m/s), 지상에서의 이동 기준


- distanceTo(Location dest)


ALocationBLocation이 있다고 할 때 두 위치의 거리 차를 구할 때 사용 합니다.

사용 방법은 : ALocation.distanceTo(Location BLocation)

 

- getTime()


주어진 위치 값을 구한 시간 정보를 가져 옵니다. ALocation 값을 구한 시간을 알고 싶다면

사용 방법 : ALocation.getTime();

 

- getSpeed()


위치의 변화가 있다면 직전 위치에서 현재 위치까지 이동하는데 소요된 시간으로 속도를

자동으로 계산해서 보여 줍니다.

ALocation에서의 속도를 구한다면

사용 방법 : ALocation.getSpeed()

 

 

2. 속도 측정 프로그램

 

2.1 신규 프로젝트 생성

 

프로젝트를 임의의 이름으로 생성해 줍니다.

 

여기서는 DeviceAndroid 4.0을 선택 하고



ActivityEmpty로 설정 했습니다.



 

2.2 Permission


위치에 대한 자료를 얻기 위해서는 장치 사용에 대한 권한 허가가 필요하고

GPS를 사용하기 위한 권한을 추가 합니다.

AndroidManifest.xml


<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">


2.3 Layout 작성

 

GridLayout을 이용해서 폼을 잡고 TextView를 두줄로 배열 했습니다.


<GridLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:columnCount="2"
    app:layout_constraintTop_toBottomOf="@+id/tvTitle"
    >

    <TextView
        android:id="@+id/tvGpsEnableLabel"
        android:layout_gravity="right"
        android:textSize="25dp"
        android:text="GPS Enable "
        />
    <TextView
        android:id="@+id/tvGpsEnable"
        android:text=":"
        android:textSize="25dp"
        />

… 이하 생략



2.4 MainActivity.java

 

- 권한 설정


AndroidManifest.xml에 추가한 권한 이외에도 Android 6.0 부터는 source 안에도 권한에 대한 체크를 하도록 하여 추가를 해줍니다.


//권한 체크
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }


- 위치정보 업데이트 등록


이동시 위치정보 업데이트를 위해 함수를 사용해 등록 합니다.


requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)


provider : 현재 위치정보 제공자가 GPS이고


minTime : 몇 초마다 정보를 update 할것인가 설정하는 최소 시간입니다.

현재 0을 주고 테스트 하는데 시간간격이 1000(1초)로 나오는 것으로 봐서 기본 1초 인듯합니다.

0으로 설정한 경우와 1000으로 한 경우 저속에서는 조금 차이가 있는 것 같습니다.

심심하면 시간과 거리 값을 조금씩 수정해서 테스트 해보세요.


minDistance : 거리 이동을 얼마나 할때마다 update 하는지에 대한 값입니다.


listener : 말 그대로 LocationListener 입니다.

 

- getSpeed()

double getSpeed = Double.parseDouble(String.format("%.3f", location.getSpeed()));

자동 속도 계산 값 입니다.  소수점 3자리로 하려고 하는데 2자리만 나오는 것으로 봐서

기본이 소수점 2자리 인 것 같습니다.

 

- 시간 간격

deltaTime = (location.getTime() - mLastlocation.getTime()) / 1000.0;

getTime()으로 얻은 시간은 milliseconds 이므로 1000 으로 나누어 주어야 m/s로 계산할 수 있습니다.

 

- 거리 간격

mLastlocation.distanceTo(location)

두 지점의 거리 차이를 구하며 meter 단위로 리턴 받습니다.

 

- 속도 계산

speed = mLastlocation.distanceTo(location) / deltaTime;

미터로 구한 거리를 시간 간격(밀리세턴드를 미터로 변경한 값)으로 나누어 구합니다.

 

- 위치 구하기 제거

ocationManager.removeUpdates(this);

프로그램이 중단 또는 종료되어 더 이상 위치를 구할 필요가 없는 경우 호출 합니다.


 

3. 결과



3.1 결과 화면

 

일정 속도로 이동하면 비슷한 결과가 나오는데 손으로 쥐고 걸어가면서 하면 두개의 값에 차이가 나는군요.


android gps 속도 측정



3.2 Source Code

 

GpsSpeed.7z



3.3 APK File


gpsSpeed.apk



4. Source Code

 


4.1 AndroidMainfest.xml

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.will.gpsspeed">

    <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>


4.2 activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="GPS Speed Test"
        android:layout_marginTop="20dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <GridLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:columnCount="2"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        >

        <TextView
            android:id="@+id/tvGpsEnableLabel"
            android:layout_gravity="right"
            android:textSize="25dp"
            android:text="GPS Enable "
            />
        <TextView
            android:id="@+id/tvGpsEnable"
            android:text=":"
            android:textSize="25dp"
            />

        <TextView
            android:id="@+id/tvGetSpeedLabel"
            android:layout_gravity="right"
            android:textSize="25dp"
            android:text="Get Speed "
            />
        <TextView
            android:id="@+id/tvGetSpeed"
            android:text=":"
            android:textSize="25dp"
            />

        <TextView
            android:id="@+id/tvCalSpeedLabel"
            android:layout_gravity="right"
            android:textSize="25dp"
            android:text="Cal Speed "
            />
        <TextView
            android:id="@+id/tvCalSpeed"
            android:text=":"
            android:textSize="25dp"
            />

        <TextView
            android:id="@+id/tvTimeLabel"
            android:layout_gravity="right"
            android:textSize="25dp"
            android:text="Time "
            />
        <TextView
            android:id="@+id/tvTime"
            android:text=":"
            android:textSize="25dp"
            />

        <TextView
            android:id="@+id/tvLastTimeLabel"
            android:layout_gravity="right"
            android:textSize="25dp"
            android:text="Last Time "
            />
        <TextView
            android:id="@+id/tvLastTime"
            android:text=":"
            android:textSize="25dp"
            />

        <TextView
            android:id="@+id/tvTimeDifLabel"
            android:layout_gravity="right"
            android:textSize="25dp"
            android:text="시간 간격 "
            />
        <TextView
            android:id="@+id/tvTimeDif"
            android:text=":"
            android:textSize="25dp"
            />

        <TextView
            android:id="@+id/tvDistDifLabel"
            android:layout_gravity="right"
            android:textSize="25dp"
            android:text="거리 간격 "
            />
        <TextView
            android:id="@+id/tvDistDif"
            android:text=":"
            android:textSize="25dp"
            />
    </GridLayout>

</android.support.constraint.ConstraintLayout>


4.3 MainActivity.java


package com.example.will.gpsspeed;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity implements LocationListener {

    private LocationManager locationManager;
    private Location mLastlocation = null;
    private TextView tvGetSpeed, tvCalSpeed, tvTime, tvLastTime, tvGpsEnable, tvTimeDif, tvDistDif;
    private double speed;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvGetSpeed = (TextView)findViewById(R.id.tvGetSpeed);
        tvCalSpeed = (TextView)findViewById(R.id.tvCalSpeed);
        tvTime = (TextView)findViewById(R.id.tvTime);
        tvLastTime = (TextView)findViewById(R.id.tvLastTime);
        tvGpsEnable = (TextView)findViewById(R.id.tvGpsEnable);
        tvTimeDif = (TextView)findViewById(R.id.tvTimeDif);
        tvDistDif = (TextView)findViewById(R.id.tvDistDif);

        //권한 체크
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

        Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (lastKnownLocation != null) {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
            String formatDate = sdf.format(new Date(lastKnownLocation.getTime()));
            tvTime.setText(": " + formatDate);  //Time
        }
        // GPS 사용 가능 여부 확인
        boolean isEnable = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        tvGpsEnable.setText(": " + isEnable);  //GPS Enable
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,0, this);
    }

    @Override
    public void onLocationChanged(Location location) {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        double deltaTime = 0;

        //  getSpeed() 함수를 이용하여 속도를 계산
        double getSpeed = Double.parseDouble(String.format("%.3f", location.getSpeed()));
        tvGetSpeed.setText(": " + getSpeed);  //Get Speed
        String formatDate = sdf.format(new Date(location.getTime()));
        tvTime.setText(": " + formatDate);  //Time

        // 위치 변경이 두번째로 변경된 경우 계산에 의해 속도 계산
        if(mLastlocation != null) {
            //시간 간격
            deltaTime = (location.getTime() - mLastlocation.getTime()) / 1000.0;
            tvTimeDif.setText(": " + deltaTime + " sec");  // Time Difference
            tvDistDif.setText(": " + mLastlocation.distanceTo(location) + " m");  // Time Difference
            // 속도 계산
            speed = mLastlocation.distanceTo(location) / deltaTime;

            String formatLastDate = sdf.format(new Date(mLastlocation.getTime()));
            tvLastTime.setText(": " + formatLastDate);  //Last Time

            double calSpeed = Double.parseDouble(String.format("%.3f", speed));
            tvCalSpeed.setText(": " + calSpeed);  //Cal Speed
        }
        // 현재위치를 지난 위치로 변경
        mLastlocation = location;
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {
        //권한 체크
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        // 위치정보 업데이트
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,0, this);
    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    @Override
    protected void onResume() {
        super.onResume();
        //권한 체크
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        // 위치정보 업데이트
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000,0, this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 위치정보 가져오기 제거
        locationManager.removeUpdates(this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //권한이 없을 경우 최초 권한 요청 또는 사용자에 의한 재요청 확인
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION) &&
                    ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
                // 권한 재요청
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
                return;
            } else {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
                return;
            }
        }

    }
}

- copy coding -


예전에 초창기 GPS 관련 자료를 얻기 위해 세미나를 찾아 다니고 자료를 수집할 때

우리나라에는 위성이 없으니 얻어 써야 하고 GPS 정보 자체가 군용으로 사용되고 있어서

일부러 오차를 약 20m 정도 나도록 신호를 주고 있다고 했었습니다.

그래서 그 20m를 보정하는 것 자체가 큰 기술이라고 했는데 이제는 핸드폰에서 아무때나

꺼내서 사용할 수 있게 되었으니 참 신기한 일입니다.

물론 그동안 수많은 지도 업체와 네비 업체가 문을 닫았지요.



1. 좌표값 생성


위치정보를 구하는 방법은 2가지가 있습니다.


1.1 GPS Provider


3각 측량의 방법으로 좌표를 위성을 이용하여 취득합니다.

그러므로 위성의 전파를 잡지 못하는 실내에서는 사용이 어렵고 실외에서는 건물 또는

계곡이 깊으면 전파를 잡기 어려워 위치를 잡지 못할 수 있습니다.


1.2 Network Provider


이동통신 기지국 또는 WiFi  access point들을 이용하여 측정을 있습니다.


1.3 Passive Provider


위치를 구하는 방법이 2가지라고 했는데 Passive 방식은 좌표를 직접 구하는 것이 아니고

다른 어플리케이션이나 서비스가 좌표 값을 구하면 단순히 값을 받아 오기만 하는

전달자 역할을 하기 때문에 값을 얻을 수는 있지만 구한다고는 없습니다.



2. LocationManager 개요



2.1 Permission


모바일 기기의 장치를 사용하려면 사용 허가가 필요합니다.

provider 별 사용 허가에 대한 변수들 입니다.

대부분 ACCESS_FINE_LOCATION 이거 하나면 권한을 받을 수 있습니다.


 Provider

 permission

 GPS

 android.permission.ACCESS_FINE_LOCATION

 Network

 android.permission.ACCESS_COARSE_LOCATION 또는

 android.permission.ACCESS_FINE_LOCATION

 Passive

 android.permission.ACCESS_FINE_LOCATION



2.2 Provider


Type 

 Parameter

 설명

 String

 GPS_PROVIDER

 GPS를 이용 위치 제공

 String

 NETWORK_PROVIDER

 기지국, WiFi를 이용 위치 제공

 String

 TYPE_STEP_COUNTER

 기존 좌표값 이용 위치 제공



2.3 Method


Type

 Method / 설명

 List

 getAllProviders()

  - 모든 Provider 정보를 리턴 한다.

 LocationProvider

 getProvider(String name)

  - 명칭(name)에 대한 Provider 정보를 리턴 한다.

 List

 getProviders(boolean enabledOnly)

  - true를 입력하면 현재 사용 가능한 Provider의 목록을 리턴 합니다.

  - false를 입력하면 비활성화 포함 모든 Provider의 목록을 리턴 합니다.

 boolean

 isProviderEnabled(String provider)

  - 입력한 Provider의 명칭에 대한 사용 가능 여부를 리턴 합니다.

 void

 removeUpdates(LocationListener listener)

  - 더 이상 위치 정보가 필요 없을 때 위치 정보 수집을 종료 시킵니다.

 void

 requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)

  - Provider를 등록하고 기입한 거리와 시간의 변동이 있을 때 마다 update 된 위치 정보를 리턴 합니다.



3. Location 프로그램



그럼 좌표 값을 얻기가 얼마나 쉬운지 한번 알아보도록 하겠습니다.



3.1 신규 프로젝트 생성


프로젝트 명을 적당하게 명명해서 생성 하고 기타 설정 사항도 본인의 기호에 맞게 설정 하여 신규 프로젝트를 하나 생성 합니다.

저는 항상 DeviceAndroid 4.0을 선택 하고



Activity Empty로 설정 합니다.




3.2 Permission


장치 사용에 대한 권한 허가는 두개 다 적어 줍니다.


AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>


3.3 Layout 작성

 

지금까지 Layout은 그냥 TextView를 죽 나열하는 방식으로 작업 했는데

이번에는 기입 하는게 많고 우측 정렬도 필요해서 GridLayout을 사용했습니다.


<GridLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:columnCount="2"
    app:layout_constraintTop_toBottomOf="@+id/tvTitle"
    >

참고로 여기서는 그냥 android:columnCount=”2” 이것만 보시면 됩니다.

컬럼이 2개 이니까 아래에 나열된 TextView들은 자동으로 2개씩 나누어져서 하나의 Row를 만듭니다.

HTMLTable tag보다 참 편하죠.

 

3.4 MainActivity.java


- 권한 설정


이미 Manifest에 권한을 추가 했지만 Android 6.0 부터는 source 안에도 권한에 대한 체크를 해야 한다는군요.

저는 location를 사용하는 모든 곳에 추가를 했습니다.

안그러면 실행은 되는데 빨간 줄이 자꾸 나와서 눈에 거슬리더군요


if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
        && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    //권한이 없을 경우 최초 권한 요청 또는 사용자에 의한 재요청 확인
    if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_FINE_LOCATION) &&
            ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_COARSE_LOCATION)) {
        // 권한 재요청
        ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
        return;
    } else {
        ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
        return;
    }
}

- 초기 좌표값


프로그램이 시작되면 우선 초기 좌표 값을 기록하도록 했습니다.


Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastKnownLocation != null) {
    double lng = lastKnownLocation.getLongitude();
    double lat = lastKnownLocation.getLatitude();
    Log.d(TAG, "longtitude=" + lng + ", latitude=" + lat);
    tvGpsLatitude.setText(":: " + Double.toString(lat ));
    tvGpsLongitude.setText((":: " + Double.toString(lng)));
}

그리고 초기 값을 나타낼 때만 중간에 콜론을 두개 찍었는데( :: ) 이러면 초기값이 그대로 인지

아니면 변경된 값을 얻어오는지 확인을 할 수 있습니다.

 

- Provider 작동 확인


기기에 어떤 Provider들이 있는지 값을 가져오고


listProviders = locationManager.getAllProviders();

Provider별 작동 여부를 확인 하여 Update가 되도록 합니다.

requestLocationUpdates()의 두번 째 값은 갱신 시간이고 세번 째 값은 갱신 이동 거리입니다.

저는 둘다 0으로 해서 계속 값을 갱신 하도록 했습니다.

이렇게요.


if(listProviders.get(i).equals(LocationManager.GPS_PROVIDER)) {
    isEnable[0] = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    tvGpsEnable.setText(": " +  String.valueOf(isEnable[0]));

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}

- LocationChange


onLocationChanged(Location location)에서 이동을 하면 좌표 값이 변경되고 변경된 좌표를 얻어옵니다.


if(location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
    latitude = location.getLatitude();
    longitude = location.getLongitude();
    tvGpsLatitude.setText(": " + Double.toString(latitude ));
    tvGpsLongitude.setText((": " + Double.toString(longitude)));
    Log.d(TAG + " GPS : ", Double.toString(latitude )+ '/' + Double.toString(longitude));
}

- 수집 중단


어플리케이션을 사용하지 않을 때는 더 이상 좌표 수집을 하지 않도록 중단해야 합니다.

안그러면 계속 백그라운드에서 작업을 하여 리소스를 잡아먹겠죠.


locationManager.removeUpdates(this);



4. 결과



4.1 결과 화면


GPS는 잘 잡히는데 Network은 안잡히는 걸로 나오네요.


gps network provider android


구해진 좌표 값은 google map과 연동하면 바로 위치를 확인 할 수 있습니다.

실제로 google map과 연동 테스트를 하려면 구글에 회원 가입을 하고

맵을 사용하겠다고 해서 API 키값을 받아야 합니다.

귀찮으니 그냥 간단하게 구글 맵에서 위치를 확인 할 수 있는데요.

구글 지도를 웹으로 열면 주소창의 URL에 좌표가 같이 나타 납니다.

그럼 거기에 핸드폰으로 구한 좌표를 콤마로 구분해서 변경해 주면 위치를 확인할 수 있습니다.

 

https://www.google.com/maps/@37.5555062,126.7976293,14z




4.2 Source Code


LocProvider.7z



4.3 APK File


LocProvider.apk




5. Full Source Code


원래 취지대로 그냥 복사해서 붙여넣기를 해서 사용할 때를 위해 전체 소스를 남김니다



5.1 AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.desk.locprovider">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_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>


5.2 activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Android Location Test"
        android:layout_marginTop="20dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <GridLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:columnCount="2"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        >

        <TextView
            android:id="@+id/tvGpsEnableLabel"
            android:layout_gravity="right"
            android:text="GPS Enable "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvGpsEnable"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvNetworkEnableLabel"
            android:layout_gravity="right"
            android:text="Network Enable "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvNetworkEnable"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvPassiveEnableLabel"
            android:layout_gravity="right"
            android:text="Passive Enable "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvPassiveEnable"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvGpsLocationLabel"
            android:layout_gravity="right"
            android:text="GPS Location "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvGpsLocation"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvGpsLatitudeLabel"
            android:layout_gravity="right"
            android:text="GPS Latitude "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvGpsLatitude"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvGpsLongitudeLabel"
            android:layout_gravity="right"
            android:text="GPS Longitude "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvGpsLongitude"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvNetworkLocationLabel"
            android:layout_gravity="right"
            android:text="Network Location "
            android:textSize="20dp"
        />
        <TextView
            android:id="@+id/tvNetworkLocation"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvNetworkLatitudeLabel"
            android:layout_gravity="right"
            android:text="Network Latitude "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvNetworkLatitude"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvNetworkLongitudeLabel"
            android:layout_gravity="right"
            android:text="Network Longitude "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvNetworkLongitude"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvPassiveLocationLabel"
            android:layout_gravity="right"
            android:text="Passive Location "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvPassiveLocation"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvPassiveLatitudeLabel"
            android:layout_gravity="right"
            android:text="Passive Latitude "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvPassiveLatitude"
            android:text=""
            android:textSize="20dp"
            />

        <TextView
            android:id="@+id/tvPassivekLongitudeLabel"
            android:layout_gravity="right"
            android:text="Passive Longitude "
            android:textSize="20dp"
            />
        <TextView
            android:id="@+id/tvPassivekLongitude"
            android:text=""
            android:textSize="20dp"
            />
    </GridLayout>
</android.support.constraint.ConstraintLayout>


5.3 MainAcitvity.java


package com.example.desk.locprovider;

import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import java.util.List;

public class MainActivity extends AppCompatActivity implements LocationListener {

    private LocationManager locationManager;
    private List<String> listProviders;
    private TextView tvGpsEnable, tvNetworkEnable, tvPassiveEnable, tvGpsLatitude, tvGpsLongitude;
    private TextView tvNetworkLatitude, tvNetworkLongitude, tvPassiveLatitude, tvPassivekLongitude;
    private String TAG = "LocationProvider";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvGpsEnable = (TextView)findViewById(R.id.tvGpsEnable);
        tvNetworkEnable = (TextView)findViewById(R.id.tvNetworkEnable);
        tvPassiveEnable = (TextView)findViewById(R.id.tvPassiveEnable);
        tvGpsLatitude = (TextView)findViewById(R.id.tvGpsLatitude);
        tvGpsLongitude = (TextView)findViewById(R.id.tvGpsLongitude);
        tvNetworkLatitude = (TextView)findViewById(R.id.tvNetworkLatitude);
        tvNetworkLongitude = (TextView)findViewById(R.id.tvNetworkLongitude);
        tvPassiveLatitude = (TextView)findViewById(R.id.tvPassiveLatitude);
        tvPassivekLongitude = (TextView)findViewById(R.id.tvPassivekLongitude);

        //권한 체크
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

        Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (lastKnownLocation != null) {
            double lng = lastKnownLocation.getLongitude();
            double lat = lastKnownLocation.getLatitude();
            Log.d(TAG, "longtitude=" + lng + ", latitude=" + lat);
            tvGpsLatitude.setText(":: " + Double.toString(lat ));
            tvGpsLongitude.setText((":: " + Double.toString(lng)));
        }
        lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        if (lastKnownLocation != null) {
            double lng = lastKnownLocation.getLongitude();
            double lat = lastKnownLocation.getLatitude();
            Log.d(TAG, "longtitude=" + lng + ", latitude=" + lat);
            tvNetworkLatitude.setText(":: " + Double.toString(lat ));
            tvNetworkLongitude.setText((":: " + Double.toString(lng)));
        }

        lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
        if (lastKnownLocation != null) {
            double lng = lastKnownLocation.getLongitude();
            double lat = lastKnownLocation.getLatitude();
            Log.d(TAG, "longtitude=" + lng + ", latitude=" + lat);
            tvPassiveLatitude.setText(":: " + Double.toString(lat ));
            tvPassivekLongitude.setText((":: " + Double.toString(lng)));
        }

        listProviders = locationManager.getAllProviders();
        boolean [] isEnable = new boolean[3];
        for(int i=0; i<listProviders.size();i++) {
            if(listProviders.get(i).equals(LocationManager.GPS_PROVIDER)) {
                isEnable[0] = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
                tvGpsEnable.setText(": " +  String.valueOf(isEnable[0]));

                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
            } else if(listProviders.get(i).equals(LocationManager.NETWORK_PROVIDER)) {
                isEnable[1] = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
                tvNetworkEnable.setText(": " +  String.valueOf(isEnable[1]));

                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
            } else if(listProviders.get(i).equals(LocationManager.PASSIVE_PROVIDER)) {
                isEnable[2] = locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
                tvPassiveEnable.setText(": " +  String.valueOf(isEnable[2]));

                locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, this);
            }

        }

        Log.d(TAG, listProviders.get(0) + '/' + String.valueOf(isEnable[0]));
        Log.d(TAG, listProviders.get(1) + '/' + String.valueOf(isEnable[1]));
        Log.d(TAG, listProviders.get(2) + '/' + String.valueOf(isEnable[2]));
    }

    @Override
    public void onProviderEnabled(String provider) {
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
        locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, this);
    }


    @Override
    public void onLocationChanged(Location location) {

        double latitude = 0.0;
        double longitude = 0.0;

        if(location.getProvider().equals(LocationManager.GPS_PROVIDER)) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            tvGpsLatitude.setText(": " + Double.toString(latitude ));
            tvGpsLongitude.setText((": " + Double.toString(longitude)));
            Log.d(TAG + " GPS : ", Double.toString(latitude )+ '/' + Double.toString(longitude));
        }

        if(location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            tvNetworkLatitude.setText(": " + Double.toString(latitude ));
            tvNetworkLongitude.setText((": " + Double.toString(longitude)));
            Log.d(TAG + " NETWORK : ", Double.toString(latitude )+ '/' + Double.toString(longitude));
        }

        if(location.getProvider().equals(LocationManager.PASSIVE_PROVIDER)) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            tvPassiveLatitude.setText(": " + Double.toString(latitude ));
            tvPassivekLongitude.setText((": " + Double.toString(longitude)));
            Log.d(TAG + " PASSIVE : ", Double.toString(latitude )+ '/' + Double.toString(longitude));
        }

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    @Override
    protected void onStart() {
        super.onStart();
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //권한이 없을 경우 최초 권한 요청 또는 사용자에 의한 재요청 확인
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_FINE_LOCATION) &&
                    ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_COARSE_LOCATION)) {
                // 권한 재요청
                ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
                return;
            } else {
                ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}, 100);
                return;
            }
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
        locationManager.removeUpdates(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
        locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, 0, 0, this);
    }
}

- copy coding -


tistory를 사용하면서 본문 내용 폰트가 너무 작아서 처음부터 변경을 하려고 생각만 하고 있다가

오랜만에 검색을 해보았지만 나오는 설명들이 나하고는 맞지가 않아 하는 수 없이

시간을 내서 직접 작업을 해보았습니다.

 

사용자 마다 스킨이 다를 텐데 저의 경우는 반응형 Square를 사용하고 있습니다.


tistory font


폰트는 다들 나눔 고딕을 많이 사용하는 것 같은데 검색을 하다 보니 본고딕(Noto Sans)

괜찮아 보여서 이것으로 선택을 하였습니다.


https://www.google.com/get/noto/#sans-kore


이곳에 가면 글씨의 원본을 볼 수 있습니다.


하단에는 캡쳐를 해왔는데 이미지가 작아서 별로인 것 같고 직접 가서 보시길 추천 합니다.

폰트는 다운로드를 받아서 설치를 하려고 했는데 생각보다 파일이 너무 크더군요.


요즘에 링크로도 해결이 되는데 굳이 다운받고 업로드 하기가 귀찮아 그냥 링크 방식으로 했습니다.




. 그럼 작업을 시작 합니다.

 

먼저 로그인을 하고 관리자 페이지 좌측 메뉴에서 [스킨 편집]을 선택 하면


우측에 [html 편집] 버튼이 보입니다.



[html 편집] 버튼을 누르면 화면이 바뀌면서 [HTML | CSS | 파일업로드] 가 나타 납니다.

 

여기서는 CSS를 선택 합니다.


아래 그림을 보고 저와 내용이 다르면 더 이상 이 글을 읽을 필요가 없습니다.


저와 css 구조가 달라서 적용이 안될 수 있습니다.



먼저 사용하지 않을 폰트는 주석처리를 하고 신규로 추가를 했습니다.


/*@import url(http://fonts.googleapis.com/css?family=Ubuntu+Condensed);*/

/*@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css);*/

@import url(http://fonts.googleapis.com/earlyaccess/notosanskr.css);


그리고 font-size:를 키우고 font-family:에 폰트를 추가 해주고 사이트를 새로고침 했는데

영향이 없습니다.


textarea { font-size: 15px; font-family: 'Noto Sans KR', sans-serif; line-height: 200%; }


그래서 모든 font-family: 를 찾아서 수정하고 별 방법을 다 했는데 저하고는 하나도 맞지가 않더군요.


결국 divspan이 좌측 메뉴 구조와 내용에 영향을 주는 tag인걸 찾아내서

그냥 아래처럼 span, div를 추가하는 것으로 마무리를 했습니다.



이제는 글씨도 좀 커지고 제가 보기에는 만족 스럽습니다.


그럼 된거죠.


- copy coding -


1···107108109110111112113···118

+ Recent posts