Android Studio 자동 저장 끄고 저장 안함 표시 하기

Android Studio에서 코딩 작업을 할 때 가장 좋으면서도 불안한 부분이 내가 실수를 했는데도 모든 소스가 자동으로 저장이 되는 기능 입니다.  가끔씩 무엇인가를 떨어뜨리거나 실수로 키보드를 잘못 누르는 경우에도 어떤 파일을 건드렸는지 찾기가 애매 한 경우 또는 추가로 작업한 부분을 다시 되돌리려고 하는 경우에는 난감하고 괴로운 상황입니다. 
간단히 몇개의 설정만으로 이런 상황을 피할 수 있습니다.

1. 자동 저장 해제

먼저 코딩을 자동으로 저장하지 않도록 설정을 합니다.  메뉴에서

File > Settings...

 

그러면 Settings 팝업 창이 나타나는데 여기서 좌측 메뉴에서

 


Appearance & Behavior > System Settings

 

 

그리고 우측 하단의 Autosave 에서 두 개의 항목을 찾아 체크가 되어 있으면 해제 합니다.
Save files if the IDE is idle for ~ seconds
Save files when switching to a different application

여기까지 작업 하면 자동 저장을 막을 수 있지만 어떤 파일이 수정은 하고 저장은 하지 않은 파일 인지 구분을 할 수 없습니다.


2. 저장하지 않은 파일에 * 표시

저장하지 않은 파일명 좌측에 * 표시를 해주기 위한 설정을 하려면 열려있는 Settings 창에서


Editor > General > Editor Tabs 


을 선택 하고 우측에서


Mark modified (*) 에 체크를 해줍니다

 

 

 

그리고 [OK] 버튼을 이용하여 설정사항을 저장하면 끝 입니다.

이제 사용을 해보도록 하겠습니다.


두개의 파일을 수정하면 아래 그림과 같이 파일명 좌측에 * 표시가 나타납니다

 

만일 수정 전으로 가고 싶으면 Ctrl+Z를 눌러주면 한 단계씩 다시 작업이 취소되며 파일명 좌측에 * 표시가 없는 상태로 변하는데 거기가 최종 저장을 해놓은 부분 입니다.  

 

파일명 좌측에 * 표시가 없어지는 상태가 최종 저장을 해놓은 부분이란 계속 Ctrl+Z를 사용할 수 있다는 얘기가 됩니다.  파일을 열고 작업을 하면서 중간에 저장을 했다면 상단 파일명을 보면서 작업 취소를 하시기 바랍니다.

 

- copy coding -

 

Activity에서 다른 Activity를 호출할 때 Intent를 이용하여 화면전환을 하는 것과 같이 핸드폰에 기본적으로 장착된 App의 Activity를 호출 하는 경우에는 Intent의 action 중 ACTION_VIEW를 이용하여 웹 브라우저를 호출하는 방법 입니다.
기본 브라우저를 이용하여 웹 페이지 URL을 연결하려면 public Intent (String action, Uri uri) 메소드를 사용하는데 action 부분에는 ACTION_VIEW를 입력하고 Uri는 웹 주소를 입력하면 됩니다.

 

Intent intentUrl = new Intent(Intent.ACTION_VIEW, Uri.parse("https://copycoding.tistory.com/"));
startActivity(intentUrl);

 

URL에 파라미터를 추가해서 넘기려면 URL 뒤에 붙여주도록 합니다.

 

String param = "/47";
Intent intentParam = new Intent(Intent.ACTION_VIEW, Uri.parse("https://copycoding.tistory.com/" + param));
startActivity(intentParam);

 

인터넷을 사용해야 하므로 Manifest에 permission을 추가해 주면 됩니다.
<uses-permission android:name="android.permission.INTERNET" />

 

버튼을 누르면 첫화면으로 이동 하고 param을 붙인경우 페이지를 찾아 갑니다.

 

 

전체 소스
수정된 파일은 3개 입니다.

AndroidManifest.xml

 

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

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

    <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/Theme.ActionViewUri">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

 

activity_main.xml

 

<?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=".MainActivity">

    <Button
        android:id="@+id/btnUrl"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="URL"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.229"
        android:onClick="clickUrl"/>

    <Button
        android:id="@+id/btnParam"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="176dp"
        android:text="URL+Param"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnUrl"
        app:layout_constraintVertical_bias="0.0"
        android:onClick="clickParam"/>
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

MainActivity.java

 

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {

   @Override protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
   }
     
  public void clickUrl(View view) {
     Intent intentUrl = new Intent(Intent.ACTION_VIEW, Uri.parse("https://copycoding.tistory.com/"));
     startActivity(intentUrl);
  }

  public void clickParam(View view) {
      String param = "/47";
      Intent intentParam = new Intent(Intent.ACTION_VIEW, Uri.parse("https://copycoding.tistory.com/" + param));
      startActivity(intentParam);
   }
}

 

- copy coding -

지난 번에 NAVER Map에서 사용 권한 아이디를 생성하고 안드로이드에서 네이버 지도를 표현하는 방법을 알아 보았습니다.

Android에서 Naver map 이용하기 위한 Client ID 생성


 이번에는 네이버 지도에서 핸드폰의 현재 위치를 표시하는 방법을 알아보려고 합니다.

 Android API 개발 가이드를 보면 FusedLocationSource를 이용한 현재 위치 표시 방법에 대해 기본적인 소스가 제공되고 있고 현재의 위치를 GPS_PROVIDER를 이용하여 좌표를 구하고 위치를 표현하는 방법도 소개가 되고 있습니다.

여기서는 제공된 소스에서 약간 생략된 부분에 대한 내용을 추가하여 설명 드립니다



1. AndroidManifest.xml

 

위치 추적에 사용되는 권한을 추가해 줍니다

 

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

그리고 네이버 API에서 생성된 사용자 ID도 manifest에 추가를 합니다.

 

<application
    ...

    <meta-data
        android:name="com.naver.maps.map.CLIENT_ID"
        android:value="네이버 API ID" />

</application>

 

2. build.gradle

 

build.gradle (Project: XXXX)

 

maven {
    url 'https://naver.jfrog.io/artifactory/maven/'
}

 

build.gradle (Module: app)

지도와 위치 정보를 사용하기 위한 의존성을 추가 합니다.

 

dependencies {
    implementation 'com.naver.maps:map-sdk:3.10.2'
    implementation 'com.google.android.gms:play-services-location:17.0.0'
}

 

이렇게 하고 Sync Now만 하면 환경설정은 완료 됩니다.

 


3. activity_main.xml

레이아웃에 지도를 표시할 fragment를 추가하고

 

<fragment android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/map"
    android:name="com.naver.maps.map.MapFragment" />

 

4. MainActivity.java

이제 구현을 하기만 하면 됩니다.

OnMapReadyCallback 을 상속받아 지도를 표시할 수 있도록 합니다.

 

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

 

지도와 위치 정보에 필요한 변수들과 권한을 정의 해 줍니다.

 

private NaverMap naverMap;
private FusedLocationSource locationSource;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1000;
private static final String[] PERMISSIONS = {
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.ACCESS_COARSE_LOCATION
};

 

 

화면을 생성할 때 지도와 현재 위치를 받아 옵니다.

 

FragmentManager fm = getSupportFragmentManager();
MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
if (mapFragment == null) {
    fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
mapFragment.getMapAsync(this);
locationSource = new FusedLocationSource(this, LOCATION_PERMISSION_REQUEST_CODE);

 

 

그리고 마지막으로 현재 위치를 지도에 표시해 줍니다.

 

public void onMapReady(@NonNull NaverMap naverMap) {
    this.naverMap = naverMap;

    naverMap.setLocationSource(locationSource);  //현재 위치
    ActivityCompat.requestPermissions(this, PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);  //현재위치 표시할때 권한 확인
}

 

위치 정보를 가져올 수 있는 권한을 사용자가 선택하도록 합니다.
화면에서 권한 부분이 제일 먼저 표시되어 허가를 하면 됩니다.

 

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(locationSource.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
        if(!locationSource.isActivated()) {
            naverMap.setLocationTrackingMode(LocationTrackingMode.None);
            return;
        } else {
            naverMap.setLocationTrackingMode(LocationTrackingMode.Follow);
        }

    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

 

 

5. 결과 화면

 

허용을 선택 합니다.

 

 

6. 전체 소스

 

- AndroidManifest.xml

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

    <uses-permission android:name="android.permission.INTERNET" />
    <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"
        android:usesCleartextTraffic="true">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.naver.maps.map.CLIENT_ID"
            android:value="네이버 API ID" />

    </application>

</manifest>

 

- build.gradle (Project: XXXX)

 

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.0.0"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://naver.jfrog.io/artifactory/maven/'
        }
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

 

 

- build.gradle (Module: app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "30.0.0"

    defaultConfig {
        applicationId "copycoding.tistory.navermap"
        minSdkVersion 16
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation 'com.naver.maps:map-sdk:3.10.2'
    implementation 'com.google.android.gms:play-services-location:17.0.0'

    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

 

- activity_main.xml

<?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=".MainActivity">

    <fragment android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map"
        android:name="com.naver.maps.map.MapFragment" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

- MainActivity.java

package copycoding.tistory.navermap;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.FragmentManager;

import android.Manifest;
import android.graphics.PointF;
import android.os.Bundle;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.naver.maps.geometry.LatLng;
import com.naver.maps.map.CameraUpdate;
import com.naver.maps.map.LocationTrackingMode;
import com.naver.maps.map.MapFragment;
import com.naver.maps.map.NaverMap;
import com.naver.maps.map.OnMapReadyCallback;
import com.naver.maps.map.overlay.Marker;
import com.naver.maps.map.overlay.PathOverlay;
import com.naver.maps.map.util.FusedLocationSource;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements NaverMap.OnMapClickListener, OnMapReadyCallback {

    private NaverMap naverMap;
    private FusedLocationSource locationSource;
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1000;
    private static final String[] PERMISSIONS = {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION
    };
    List<LatLng> lstLatLng = new ArrayList<>();

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

        FragmentManager fm = getSupportFragmentManager();
        MapFragment mapFragment = (MapFragment)fm.findFragmentById(R.id.map);
        if (mapFragment == null) {
            fm.beginTransaction().add(R.id.map, mapFragment).commit();
        }
        mapFragment.getMapAsync(this);
        locationSource = new FusedLocationSource(this, LOCATION_PERMISSION_REQUEST_CODE);

    }

    @Override
    public void onMapReady(@NonNull NaverMap naverMap) {
        this.naverMap = naverMap;
        naverMap.setLocationSource(locationSource);  //현재위치 표시
        ActivityCompat.requestPermissions(this, PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        if(locationSource.onRequestPermissionsResult(requestCode, permissions, grantResults)) {
            if(!locationSource.isActivated()) {
                naverMap.setLocationTrackingMode(LocationTrackingMode.None);
                return;
            } else {
                naverMap.setLocationTrackingMode(LocationTrackingMode.Follow);
            }

        }

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

- copy coding -

 

프로그램을 하면서 개인적으로 가장 많이 사용하는 기능이 찾기인 것 같습니다.
Android Studio에서는 프로젝트에 생성된 파일들 중에 특정 단어에 대한 검색과 관련 해서 Edit > Find 메뉴에 대부분의 기능과 단축키가 정리되어 있습니다.

 

 

이중에서 제일 많이 사용하는 찾기 기능은 Find(Ctrl + F)와 Replace(Ctrl + R) 이겠죠.

 

 

 

위 그림은 Ctrl +F 를 이용하여 찾기를 하는 내용인데 찾으려는 단어가 노란색으로 처리되어 쉽게 구분이 되어 있습니다.
그리고 Find Next(F3)은 찾는 단어를 하나씩 선택해 주는 기능으로 필요한 부분만 수정하는데 유용하게 사용 됩니다.

오늘은 전체 프로젝트에서 특정 단어를 찾아보려는 경우 사용하는 기능입니다.  메뉴에서 선택 해도 되고 단축키로 간단하게 찾기 창을 오픈 합니다.

전체 찾기 : Find In Path (Ctrl + Shift + F)

 

 

 

단어를 입력하면 상단에 찾는 단어가 포함된 파일의 위치를 보여주는 리스트가 나타나고 리스트를 하나씩 선택하면 하단에 파일의 전체 내용에서의 위치를 상세히 보여줍니다.
한가지 아쉬운 점은 File mask를 이용하여 특정 파일종류를 선택할 수 있지만 eclipse처럼 여러개를 선택할 수 없습니다.


전체 바꾸기 : Replace in path (Ctrl + Shift + R)

전체 바꾸기라기 보다는 전체에서 바꾸기가 정확한 표현일것 같네요.

 

 

 

찾는 단어와 변경할 단어를 입력해 주고 하단 버튼을 이용하여 하나씩 또는 전체를 한꺼번에 수정해 주면 됩니다.
단축키를 많이 알고 있으면 코딩 속도가 그만큼 향상 됩니다.  유용한 단축키 들을 정리해서 잘 사용하세요.

 

- copy coding -


1234567···17

+ Recent posts