android





멋모르고 안드로이드 스튜디오를 업데이트 했더니 역시나 포풍에러가 발생...


진심 업데이트는 할게 못된다. 하지만 언젠가 해야할테니 매도 먼저 맞아보자는 생각이었지만 매는 마지막에 맞는게 낫다.


아래와 같은 에러를 내뿜는데   AAPT2 이놈이 뭔가 문제를 일으킨거 같았다.


해결링크 https://stackoverflow.com/questions/46988102/errorcom-android-tools-aapt2-aapt2exception-aapt2-error-check-logs-for-detail





Error:failed processing manifest.

Error:java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details

Error:java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details

Error:com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details

Error:Execution failed for task ':app:processDebugResources'.

> Failed to execute aapt



해결책은


프로젝트 내에 gradle.properties  파일을 연다.




거기에 이 코드를 추가해준다.

android.enableAapt2=false


그리고 Sync Now를 눌러준다.

그럼 다시 프로젝트가 돌아가면서 에러가 발생하지 않았다



업데이트는 정말 조심해야될 행동이다.



  1. ww 2018.01.29 17:04 신고

    ㅠㅠ 감사합니다.

  2. \ 2018.02.02 00:23 신고

    감사합니당 ㅜㅜㅜㅜ

  3. 1 2018.02.04 19:55 신고

    굿굿~ ~~

  4. 김준석 2018.02.08 11:30 신고

    이것으로 해결을 할수 있어도 다른 문제는 없나요?
    false로 둠으로서 AAPT2 를 이용 안하려는거 같은데, 이러면 AAPT1 이 후에 삭제가 될수도 있다는게 stackoverflow에 있는데, 문제가 전혀 없는지 궁금합니다.

    • yonoo88 2018.02.08 11:32 신고

      그부분까지는 제가 확인을 할 수가 없네요ㅜ. 일단 급한대로 해결한거라 추후에 문제생기면 그 때 다시 찾아보려구 합니다

  5. 한으 2018.02.16 13:08 신고

    첫 발걸음 떼다가 이게 자꾸 에러가 떠서 못 나가고 있었는데 덕분에 해결했습니다 감사합니다ㅠㅜ

    • yonoo88 2018.02.16 13:15 신고

      설 연휴에도 열일하시네요
      도움이 되었다니 다행입니다!

    • 한으 2018.02.16 14:21 신고

      근데 자바도 모르고 이해할만한 적당한 교재나 강좌도 찾지 못해서 힘이 드네요. 어떻게 시작하면 좋을까요?

    • yonoo88 2018.02.16 14:33 신고

      교재는 그냥 시중이 가장 인기있는 교재 하나 사서 하시면 될거에요. 요즘은 교재사면 인터넷강좌도 무료로 푸는게 많을거에요. 제일 좋은건 직접 만들어보면서 부딪히는게 좋은거 같아요

    • 한으 2018.02.17 21:01 신고

      조언 감사드립니다!

    • yonoo88 2018.02.17 21:03 신고

      저도 앱개발이 직업은 아닌지라 손 놓고 있네요..아직 많이 부족한데 의지가 제일 중요한거 같아요 파이팅 하세요!





https://blog.stylingandroid.com/permissions-part-3/

위 블로그 글을 참고 하였고 

프로젝트는 작성자의 깃허브 사이트 

https://github.com/StylingAndroid/Permissions/tree/Part3

를 참고 하였다.


프로젝트를 실행하면 이러한 모습이다



코드를 참고하면서 내 프로젝트에 필요한 것만 참고함.


먼저

PermissionsActivity.java 와 PermissionsChecker.java를 프로젝트에 붙여넣기 하였다.

추가 설명은 코드 내 주석을 달아놓았다.



PermissionsActivity.java

37라인

setContentView(R.layout.new_custom_full);

이 부분은 팝업을 표시할 액티비티의 xml 파일명으로 변경해준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
 
 
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
 
public class PermissionsActivity extends AppCompatActivity {
    public static final int PERMISSIONS_GRANTED = 0;
    public static final int PERMISSIONS_DENIED = 1;
 
    private static final int PERMISSION_REQUEST_CODE = 0;
    private static final String EXTRA_PERMISSIONS = "com.stylingandroid.permissions.EXTRA_PERMISSIONS";
    private static final String PACKAGE_URL_SCHEME = "package:";
 
    private PermissionsChecker checker;
    private boolean requiresCheck;
 
    public static void startActivityForResult(Activity activity, int requestCode, String... permissions) {
        Intent intent = new Intent(activity, PermissionsActivity.class);
        intent.putExtra(EXTRA_PERMISSIONS, permissions);
        ActivityCompat.startActivityForResult(activity, intent, requestCode, null);
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) {
            throw new RuntimeException("This Activity needs to be launched using the static startActivityForResult() method.");
        }
        setContentView(R.layout.new_custom_full); //xml 파일명 변경 필요
 
        checker = new PermissionsChecker(this);
        requiresCheck = true;
    }
 
    @Override
    protected void onResume() {
        super.onResume();
        if (requiresCheck) {
            String[] permissions = getPermissions();
 
            if (checker.lacksPermissions(permissions)) {
                requestPermissions(permissions);
            } else {
                allPermissionsGranted();
            }
        } else {
            requiresCheck = true;
        }
    }
 
    private String[] getPermissions() {
        return getIntent().getStringArrayExtra(EXTRA_PERMISSIONS);
    }
 
    private void requestPermissions(String... permissions) {
        ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);
    }
 
    private void allPermissionsGranted() {
        setResult(PERMISSIONS_GRANTED);
        finish();
    }
 
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) {
            requiresCheck = true;
            allPermissionsGranted();
        } else {
            requiresCheck = false;
            showMissingPermissionDialog();
        }
    }
 
    private boolean hasAllPermissionsGranted(@NonNull int[] grantResults) {
        for (int grantResult : grantResults) {
            if (grantResult == PackageManager.PERMISSION_DENIED) {
                return false;
            }
        }
        return true;
    }
 
    //모두 거부 하였을 때 나타나는 팝업 창 설정입니다.
    private void showMissingPermissionDialog() {
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(PermissionsActivity.this);
        dialogBuilder.setTitle(R.string.help); //팝업 창 타이틀
        //팝업 안내 메시지 부분으로 string.xml에서 설정한 메시지를 노출합니다.
        dialogBuilder.setMessage(R.string.string_help_text);
        //팝업 창 버튼 2개를 노출합니다.
        //확인버튼을 누르면 앱 종료?인데 저는 팝업 창만 사라졌네요
        dialogBuilder.setNegativeButton(R.string.quit, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                setResult(PERMISSIONS_DENIED);
                finish();
            }
        });
        //설정 버튼을 누르면 설정 화면으로 이동합니다.
       dialogBuilder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                startAppSettings();
            }
        });
        dialogBuilder.show();
    }
 
     private void startAppSettings() {
        Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName()));
        startActivity(intent);
    }
}
cs



PermissionsChecker.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat;
 
class PermissionsChecker {
    private final Context context;
 
    public PermissionsChecker(Context context) {
        this.context = context;
    }
 
    public boolean lacksPermissions(String... permissions) {
        for (String permission : permissions) {
            if (lacksPermission(permission)) {
                return true;
            }
        }
        return false;
    }
 
    private boolean lacksPermission(String permission) {
        return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED;
    }
 
}
 
cs


발생하는 에러는 알맞게 처리한 다음

AndroidMenifest.xml 에 PermissionsActivity를 추가해준다.

1
2
3
4
5
6
7
8
9
10
        <!--PermissionsActivity 를 추가해줍니다.-->
        <!--팝업 적용을 위해 @style:AppTheme 추가해줍니다-->
        <activity
            android:name="com.yonoo.my.PermissionsActivity"
            android:configChanges="orientation|screenSize|screenLayout|keyboard|keyboardHidden"
            android:label="@string/app_name"
            android:theme="@style/AppTheme"
            android:screenOrientation="nosensor" >
        </activity>
 
cs


권한도 추가

1
2
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.CAMERA" />
cs



앱 테마 적용을 위해 style.xml에 다음을 추가해준다.

(다국어 설정이 되어있다면 국가별 style.xml에도 추가해준다.)

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<resources>
 
    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>
    <!--팝업 호출을 위해 아래 스타일이 필요합니다.-->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    </style>
</resources>
 
cs


그리고 권한 팝업 노출시 권한 설명을 위한 메시지를 string.xml에 추가하여준다. 마찬가지로 다국어 string에도 추가

이 메시지는 PermissonsActivity의 showMissingPermissionDialog에서 사용된다.

1
2
3
4
5
6
    <!--권한 팝업에서 노출될 메시지를 설정합니다.-->
    <string name="settings">설정</string>
    <string name="help">Help</string>
    <string name="string_help_text"> 저장소와 카메라 권한이 필요합니다. </string>
    <string name="quit">확인</string>
 
cs


그리고 권한 팝업을 띄울 액티비티파일에 다음 코드를 추가해준다.

ex) NewCustomFullActivity 에 권한 팝업을 띄울거라면 변수를 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class NewCustomFullActivity implements OnClickListener{
 
    //권한 체크를 위한 값 선언
    private static final int REQUEST_CODE = 0;
    /*요청받은 권한을 설정합니다. 여기선 저장소와 카메라를 설정
    * android.Manifest.permission.WRITE_EXTERNAL_STORAGE
    * android.Manifest.permission.CAMERA
    * */
    private static final String[] PERMISSIONS = 
            new String[]{
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    android.Manifest.permission.CAMERA
            };
    //PermissionChecker를 사용하기 위해 선언
    private PermissionsChecker checker;
cs


OnCreate에 다음 코드 추가

1
2
//Oncreate 에서 Checker를 호출
checker = new PermissionsChecker(this);
cs


그리고 다음 함수를 추가해준다.

1
2
3
    private void startPermissionsActivity() {
        PermissionsActivity.startActivityForResult(this, REQUEST_CODE, PERMISSIONS);
    }
cs


이제 팝업을 어디서 띄울지 결정해야했는데 카메라를 선택했을 때 띄우기로 결정

그래서 startActivityForResult(intent, PICK_FROM_CAMERA); 이 부분이 호출될 때 팝업이 뜨게 하였다.

권한 때문에 SecurtiyException 이 발생할 때

1
2
3
4
    //권한을 체크
    if (checker.lacksPermissions(PERMISSIONS)) {
        startPermissionsActivity();
    }
cs

이 부분을 추가해주어 권한 허용 유무를 체크하여 미허용상태면 팝업을 띄우도록 startPermissionsActivity() 을 요청한다.


추가된 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//카메라를 호출할 때 권한이 없으면 권한요청팝업이 뜨도록 설정
try{
    startActivityForResult(intent, PICK_FROM_CAMERA);
}catch (SecurityException e) {
    //권한을 체크
    if (checker.lacksPermissions(PERMISSIONS)) {
        startPermissionsActivity();
    }
    //토스트로 안내메시지도 같이 호출해보았습니다.
    e.printStackTrace();
    if(language.equals("en"|| language.equals("th"|| language.equals("vi"))
        Toast.makeText(getApplicationContext(),
                "check phone settinig >  application manager > app permission Camera approve",
                Toast.LENGTH_LONG).show();
    else
        Toast.makeText(getApplicationContext(),
                "설정 > 애플리케이션 관리자 >앱권한에서 카메라 권한을 허용해주세요",
                Toast.LENGTH_LONG).show();
}
cs


이렇게 해주면 카메라를 킬 때 허용 팝업이 노출된다.


외국인 블로거가 짜놓은 코드를 사용하였기 때문에 자세한 설명보다는 크게 크게 이해해보려고 하였다.

나중을 위해서 적어 놓은건데 빼 먹은 건 없나 모르겠다.


원래는 앱 시작하자마자 팝업 띄우려고 헀는데 뭔가 계속 안된다.. 

그래서 그냥 해당기능 켤 때  띄우는 걸로..


이런 걸 취미로 포스팅 하는 개발자들은 참 대단하다.

난 아무리 봐도 이해가 안가는데..





자주 쓰게 되는 것만 정리


Ctrl + D : 라인복제 또는 선택블록 복제

Ctrl + Y : 라인삭제


소스코드 정렬

Ctrl + Alt + L


Import 정리

Ctrl + Alt + O


Surround With (if / else, try / catch 등 블록 자동생성)

Ctrl + Alt + T


선언된 곳 찾아가기

Ctrl + B 또는 Ctrl + Click(Mouse)


Ctrl + Delete : 단어 끝까지 삭제

Ctrl + Backspace : 단어 처음까지 삭제


소스 코드 줄 이동

Alt + Shift + Up : Move Line Up

Alt + Shift + Down : Move Line Down


메소드 이동

Alt + Up : Move Up

Alt + Down : Move Down


Ctrl + Alt + I : 자동 들여쓰기


Shift + F6 : 이름 바꾸기

Alt + Delete : 안전하게 삭제(지우기전에 사용된곳 확인 가능)


Alt + Up/Down : 이전/다음 함수 이동

Ctrl + ] / [ :  코드블럭 처음/끝 이동



shift + F9 : 디버그 실행
F9 : 다음 중단점까지 진행
F7 : 중단점의 메소드 속으로 들어가서 진행
shift + F8 : 메소드 속에 들어갔던 진행에서 메소드를 빠져나옴
F8 : 한줄씩 실행
Alt + F9 : 커서를 원하는 라인에 놓고 누르면, 커서가 있는 곳까지 실행
하지만 중간에 중단점이 있으면 중단점까지 실행
Ctrl + Alt + F9 : 커서가 있는 위치까지 실행, 중간에 중단점이 있어도 무시
Ctrl + Shift + F8 : 모든 중단점 위치 확인
Ctrl + F2 : 디버그모드 종료. 일반 실행 모드로 전환


그 밖에 참고

http://www.androidside.com/bbs/board.php?bo_table=B56&wr_id=26482

http://kkangeva.tistory.com/42



Android API 23 에서 바뀐 부분이 있나보다

코드에서 getDrawable 부분에서

  'getDrawable(int)' is deprecated more...

이게 발생했다.

수정 방법은 다음과 같았다

기존 코드

img_season = (BitmapDrawable)context.getResources().getDrawable(getMap().get(str_season));


수정 코드

img_season = (BitmapDrawable) ContextCompat.getDrawable(context, getMap().get(str_season));



ContextCompat 를 추가하고 나서 아래 사진처럼 뜨는데 Alt + Enter를 해주면 정상적으로 적용된다.







Android Run 시 아래와 같은 에러가 났을 경우


[2016-02-15 11:25:55 - Dex Loader] Unable to execute dex: Multiple dex files define

[2016-02-15 11:25:55 - Test] Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define


android-support-v7-appcompat 프로젝트가 Library 에 추가 되었는지 확인해본다.


해당 프로젝트 우클릭 - Properties - Android 탭 하단에서 볼 수 있다.


Library 를 보면 android-support-v7-appcompat 프로젝트가 추가 되었는지 볼 수 있는데 필자의 경우 android-support-v7-appcompat 라이브러리가 사라져 있었다.






이런 경우 android-support-v7-appcompat 라이브러리 프로젝트를 따로 import 시켜주어야 한다. 



이 프로젝트는 아마 처음 Android Project를 새로 생성할 때 OS 4.4.4 킷캣 이상 버전으로 생성하면 자동으로 생성되었던 라이브러리이다.

(android-support-v7-appcompat 이게 생성 안되게 프로젝트를 생성하는 방법이 있다곤 하는데 우선 급한 불 부터 꺼보겠다)


그런데 이게 가끔 지멋대로 프로젝트가 사라진다거나 이상하게 깨지는 경우가 많다. 

그래서 이게 생성안되게 새 프로젝트 생성시 4.1.2로 만들곤 한다.


혹시 몰라 첨부..


android-support-v7-appcompat.zip



android-support-v7-appcompat를 import 하였다면 이제 작업하는 프로젝트에 추가해주어야 한다.


Add 버튼을 누르면 라이브러리 프로젝트 선택화면이 나온다.




android-support-v7-appcompat를 선택하고 ok를 누르면







초록색으로 체크표시가 되고 추가가 될 것이다. Apply를 눌러 적용시키고


이제 다시 한번 프로젝트를 Run 해본다.


그래도 안된다면 다음 링크를 참고해본다.


http://stackoverflow.com/questions/7870265/unable-to-execute-dex-multiple-dex-files-define-lcom-myapp-rarray


http://www.androidside.com/bbs/board.php?bo_table=B56&wr_id=27196





안드로이드 팝업창 띄우기


일단 팝업창 띄우기 예제는 많기는 한데 용도가 경고하거나 알림용이다


나는 그런 용도보다는 설명용이라 아예 xml파일을 팝업창에 보여주고 싶었다.


우선 팝업창을 만드는 작업이 필요하다.





일단 팝업창 띄우기 위한 버튼


버튼을 만들 xml파일에 만들어준다.

ex)hidden.xml



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/alert"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="히든설명" />
  
</LinearLayout>



이제 액티비티 설정부분

버튼 만든 해당 액티비티에 만들어준다.


ex)HiddenActivity.java



import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MessageDemo extends Activity implements View.OnClickListener{
	Button alert; //팝업버튼선언

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		//팝업버튼 설정
		alert=(Button)findViewById(R.id.alert);//R.id.alert는 팝업버튼 아이디
		alert.setOnClickListener(this);
		
	}
	public void onClick(View view){
		if(view==alert){ //view가 alert 이면 팝업실행 즉 버튼을 누르면 팝업창이 뜨는 조건
			new AlertDialog.Builder(this)
			.setTitle("히든목록") //팝업창 타이틀바
			.setMessage("FinessShot")  //팝업창 내용
			.setNeutralButton("닫기",new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dlg, int sumthin) {
					//닫기 버튼을 누르면 아무것도 안하고 닫기 때문에 그냥 비움

				}
			})
			.show(); // 팝업창 보여줌
		}
		
	}
}





여기까지 해주면 히든설명 이라는 버튼을 누르면 팝업창이 뜨게된다.



하지만 팝업창에서 보여줄 내용이 많을때 이렇게 하면 내용이 짤리고 공간이 부족했다.



그래서 이제부터 xml파일을 하나 만들고 그 내용들을 팝업창에 보여주도록 할 것이다.


우선 팝업창에 보여줄 xml파일을 따로 만든다


ex) dialog.xml


내용이 길어서 스크롤뷰를 적용하였다.

23번째 줄 android:text= "여기에 표시해줄 내용을 쓴다"




<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/popup" <!-- 아이디 선언, 액티비티에서 필요함-->
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#191A19"
    android:orientation="vertical"
    tools:context=".HiddenActivity" > <!--해당 액티비티 선언-->    
     <LinearLayout
       
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
   
       
    <TextView
       
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textColor="#B4B4B4"
       android:layout_gravity="center"
       android:textSize="15sp"
       android:text=" -Argues With Officials : 애매한 판정일 경우 심판과 언쟁을 함\n\n -Avoids Using Weaker Foot : 약한발은 잘 사용하지 않음\n\n -Cautious With Crosses : 코너킥 및 크로스에 대해 인터셉트 시도 보단 골 라인을 지키려 한다\n\n -Comes For Crosses : 코너킥 및 크로스에 대해 적극적으로 인터셉트를 시도한다\n\n -Corner Specialist : 코너킥 시 좀더 많은 골 찬스를 발생시킴 \n\n -Counter Attacker : 역습상황으로 전환할때의 반응속도가 향상됨\n\n -Diver : 태클을 당하면 넘어지면서 반칙을 유도함\n\n -Dives Into Tackles : 슬라이딩 태클을 자주 시도함\n\n -Early Crosser : 얼리크로스 능력치 뛰어남\n\n -Fancy Feet : 보다 정교하고 화려한 퍼스트 터치 발동\n\n -Finesse Header : 정확한 헤딩을 시도함\n\n -Finesse Shot : 정확한 슛팅을 시도함\n\n -Flair : 공을 받거나 받은 후에 일정한 공간과 시간이 있다면 자발적으로 트릭을 사용함\n\n -Forward pushes wide left : 공격시 왼쪽을 선호하는 움직임\n\n -Forward pushes wide Right : 공격시 오른쪽을 선호하는 움직임\n\n -Giant Thorw in : 드로잉을 아주 멀리 던짐 \n\n -GK Long Throw : 골킥을 멀리 찰 수 있음\n\n -GK One On One : 1:1상황에서의 방어능력이 뛰어남\n\n -GK Puncher : 펀칭의 능력이 뛰어나고 자주시도함\n\n -GK up for Corners : 키퍼가 경기종료시간이 얼마 안남았을때 코너킥 상황에 공격하러 올라감\n\n -Heel Passer : 힐패스능력이 뛰어남\n\n -High Determination : 지고있는 상황에서 일관성 상향\n\n -Holds Up : 공격상황에서 몸싸움 경합시 밸런스 상향..."
       android:textStyle="bold"
       android:typeface="normal" />
    </LinearLayout>

    
    </ScrollView>




이제 액티비티에 코드를 수정하자


HiddenActivity.java 파일로 돌아가서 onClick 함수에서 선언한 부분을 수정한다.





public void onClick(View view){
		if(view==alert){ //view가 alert 이면 팝업실행 즉 버튼을 누르면 팝업창이 뜨는 조건
			Context mContext = getApplicationContext();
			LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(LAYOUT_INFLATER_SERVICE);

			//R.layout.dialog는 xml 파일명이고  R.id.popup은 보여줄 레이아웃 아이디
			View layout = inflater.inflate(R.layout.dialog,(ViewGroup) findViewById(R.id.popup));
			AlertDialog.Builder aDialog = new AlertDialog.Builder(CustomActivity.this);
		
			aDialog.setTitle("히든스탯 목록"); //타이틀바 제목
			aDialog.setView(layout); //dialog.xml 파일을 뷰로 셋팅
		
			//그냥 닫기버튼을 위한 부분
			aDialog.setNegativeButton("닫기", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int which) {
			}
		});
		//팝업창 생성
		AlertDialog ad = aDialog.create();
		ad.show();//보여줌!
	}




이렇게 해준 뒤 실행해보면





이런 식으로 스크롤 뷰로 팝업창에 나타난다. 

한마디로 팝업창안에 xml 파일내용이 들어가서 보여준다.



  1. sss 2014.03.23 15:30 신고

    뒤로가기 눌러서 없어지지 않게하려면 어떻게하나요

    • yonoo88 2014.03.23 16:21 신고

      뒤로가기 버튼으로 팝업창을 안 없어지게 말씀이신가요?

      뒤로가기 버튼은 거의 고정적인 버튼이라 그 부분은 저도 잘 모르겠네요

  2. 이재승 2014.09.20 19:12 신고

    감사합니다~~~ 잘 쓸게요 ㅎㅎㅎ

  3. 이재승 2014.10.28 15:43 신고

    하나만 더 여쭤봐도 될까요? 한 화면에 버튼 2개를 만들어서 각각 다른 팝업 창 띄우려면 액티비티를 어떻게 수정해줘야 하나요??

    • yonoo88 2014.10.28 21:06 신고

      우선 버튼 하나를 더 만드세요 alert2 이런식으로 만드시고
      다른 팝업창에 띄울 xml 파일도 하나 만드시구요.

      onClick 메소드 안에 if 문 보이시죠? 거기에 view==alert 이게 alert 버튼을 눌렀을 때 수행되는 코드인데요.

      if문을 alert2 를 사용해서 하나더 만드는거죠.
      else if(view==alert2) { ... }
      이런 식으로 다른 팝업창 띄울 코드를 안에 써주면 되실거에요

  4. 이재승 2014.10.29 10:14 신고

    오오오 적용되네요 ㅎㅎㅎ 정말정말 감사합니다 ㅎㅎㅎㅎ

  5. 이동우 2015.02.05 21:14 신고

    맨 밑에 CustomActivity.this 부분이랑
    aDialog.setView(layout) 이 두부분이 빨간줄이뜨네요 ㅠㅠ

  6. ssddff521 2016.01.30 10:54 신고

    Error:Execution failed for task ':app:processDebugResources'.
    > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'F:\SDK\build-tools\23.0.2\aapt.exe'' finished with non-zero exit value 1
    이라는 에러가 듭니다.

    • yonoo88 2016.01.30 10:55 신고

      첨보는 에러인데 이건 코드상 문제라기보다 뭔가 이클립스 셋팅에러인거 같습니다. 경로가 sdk 쪽인데 한번 찾아보시면 될 것 같습니다

  7. 라노스 2016.06.01 17:36 신고

    AlertDialog ad = aDialog.create();
    ad.show();//보여줌!

    ad.show에서 show가 없다는 오류가 뜨는데 왜그런 걸까요?

    • yonoo88 2016.06.01 17:39 신고

      혹시
      import android.app.AlertDialog;

      이게 임포트 되어있으신가요?

  8. 우엥 2017.05.30 19:03 신고

    xml 내용을 띄우고 xml에 버튼이 있을 경우 버튼 클릭시 이벤트 처리를 또 하고 싶은데 방법이 있나요?

    • yonoo88 2017.06.03 03:20 신고

      이 글 예시로 보면 hiddenactivity에 버튼을 구현하고 이벤트 처리하시면 될겁니다.

  9. guppy 2018.10.05 14:58 신고

    안녕하세요
    일회성 팝업창을 만들고 싶은데 혹시 어떻게 해야할지 알려주실수 있으신가요?



안드로이드에서 에디트텍스트에 문자를 입력하면 자동완성으로 리스트를 보여주는 기능이다.


이 방법보다 더 나은게 있을지도 모르지만 데이터가 많을 경우 노가다가 필요한 작업인거 같다.


일단 급한대로 이걸 썼다.


국기 이미지 때문에 쓴건데 국가가 너무 많아서 힘들었다 ㅠㅠ


먼저  custom.xml 작업부분

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent"

    >

    <AutoCompleteTextView

        android:layout_height="wrap_content"

        android:layout_width="fill_parent"

        android:id="@+id/edit_national"

        android:hint="Type some text here"/>

</LinearLayout>



그리고 자바 부분에서


import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;


public class CustomActivity implements OnClickListener{

	

	private AutoCompleteTextView autoText;
  	private ArrayList<String> list;
   	private ArrayAdapter<String> adapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.custom);//해당 xml
	
	autoText= (AutoCompleteTextView)findViewById(R.id.edit_national);

        list = new ArrayList<String>();
        list.add("가나"); //리스트에 문자열을 하나씩 넣는다.자동완성에 필요한 값들이다.
        list.add("가봉");
        list.add("그리스");
        list.add("기니");
        list.add("나이지리아");
	.
	.
	.
	.

   
 
        adapter = new ArrayAdapter<String>(this, 
                android.R.layout.simple_dropdown_item_1line, list);
         
        autoText.setAdapter(adapter);



이렇게 해주면 에디트 텍스트에서 글자를 입력하면 아래에 해당 단어 리스트가 자동으로 뜨게 된다.

이건 가장 단순한 방법이고 좀 더 효율적이 방법이 있을 것이다.





어플을 만드는데 현재화면 캡쳐가 아닌 레이아웃을 캡쳐하는 기능이 필요했다.

그것도 전체 레이아웃이 아닌 상단 바를 제외한 부분 레이아웃캡쳐였다.


그래서 인터넷에 검색하여 아주 간단한 화면캡쳐소스를 구해 돌려보았다. 


그런데 내 테스트기기 중 2.2프로요 기기에서는 잘 되는데 4.0 아이스크림 기기에서는 안되는 것이었다.

요즘 누가 2.2 쓰나 . 4.0에서 작동되는게 중요했기 때문에 계속 해결책을 찾아보았다.


소스상에는 문제가 없으나 어플을 실행하고 캡쳐버튼을 누르면 자꾸 강제종료가 되었다.

로그캣에서는 Bitmap이 널 값이 난다고 나와있었다.

container.buildDrawingCache();
container.setDrawingCacheEnabled(true);
Bitmap captureView = container.getDrawingCache();//비트맵 널 값에러나는 부분

그래서 로그로 container.getDrawingCache(); 이걸 출력해보니 이게 널 값이라고 떴다. 이게 문제였다.

그래서 위 소스를 활용한 간단한 캡쳐예제를 두 테스트기기에서 돌려보니 잘 되었다.

이 예제였다. 용돈벌기 책 예제이다.

CapturePartEx.zip


??

2.2 ,4.0 둘 다 캡쳐가 잘된다. 


이걸 그대로 따라서 적용해보았는데

뭐야 같은 방식인데  똑같이 따라한건데 왜 예제는 되고 내가하면 안되는거지..

미쳐버릴 노릇이었다. 



슈퍼삽질을 해보니 안드로이드 버전에 따른 API기능상 문제는 아니라는 결론을 내렸고

다른 방법으로 캡쳐하는 방법을 찾아보기로 했다.


그래서 온갖 구글링을 찾아 헤매다가 거의 두 달만에 해결을 했다.


https://groups.google.com/forum/#!searchin/android-developers/android$20getDrawingCache/android-developers/VQM5WmxPilM/gYHJGQZh7hMJ


여기 있는 걸 따라해봤더니 갑자기 된다..

바로 캡쳐하지않고 캔버스에 그려서 캡쳐하는 방식인 것 같았다.


 int width_container = container.getWidth() ;//캡쳐할 레이아웃 크기

 int height_container = container.getHeight() ;//캡쳐할 레이아웃 크기



container.setDrawingCacheEnabled(true);

container.buildDrawingCache(true);


/***********************핵심부분**********************************/
Bitmap captureView = Bitmap.createBitmap(container.getMeasuredWidth(), 

 container.getMeasuredHeight(), Bitmap.Config.ARGB_8888); 

Canvas screenShotCanvas = new Canvas(captureView ); 

container.draw(screenShotCanvas); 
/***********************핵심부분*****************************************/


	                FileOutputStream fos; 		

 			Intent it3=getIntent();	

 			String str_name=it3.getStringExtra("it3_name");	 			



 			File fileRoute = null;

 			fileRoute = Environment.getExternalStorageDirectory(); 		



 			try {

 				File path = new File(fileRoute,"temp");

 				if(!path.exists()){//if(!path.isDirectory()){

 					path.mkdirs();

 				} 		



 				fos = new FileOutputStream(fileRoute+"/temp/"+str_name+"-.jpeg");

 				Log.d("[screenshot]", " : " + container.getDrawingCache());

 				captureView.compress(Bitmap.CompressFormat.JPEG, 100, fos);

 				container.setDrawingCacheEnabled(false); 		



 			}catch (FileNotFoundException e) {

 				e.printStackTrace();

 			}



이 방법을 쓰니 해결이 되었다.


진짜 온갖 안드로이드 커뮤니티에 글도 올려보고 책 저자에게 메일도 보내고 별 짓 다 해봤는데 안되니까 정말 짜증났다. 진짜 번역기 돌려서 스택오버플로우에도 올려봤는데 아무도 대답을 안해주고..


진짜 90퍼 완성해놓고 남은 하나 때문에 시간낭비하는 건 도무지 못 해먹겟다.ㅜㅜ

이 글로 다른 누군가가 삽질할때 도움이 되었으면 좋겠다.




  1. 감사! 2014.04.04 21:03 신고

    삽질의 해결책이 여기 있네요...감사합니다!

    • yonoo88 2014.04.04 22:59 신고

      오 해결되셨나요. 정말 다행입니다. 삽질만큼 짜증나는 일이 없죠..

  2. 조셉 2014.05.30 10:58 신고

    스택오버에서 자주쓰는 코멘트를 쓰고싶네요!!

    you save my day!!

    감사합니다.

    • yonoo88 2014.05.30 21:07 신고

      감사합니다!

      저도 스택오버플로우에서 본 해결책이었네요

  3. 방문객 2014.09.04 15:46 신고

    와..이문제로 정말 고생했었는데 ㅠㅠ감사합니다!

    • yonoo88 2014.09.04 15:52 신고

      해결되셨나요 다행입니다. 아직도 왜 많이들 쓰는 캡쳐방식은 안되는지 모르겠네요..

  4. pong 2014.09.15 16:03 신고

    감사~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  5. 디트 2014.09.18 12:04 신고

    정말 정말 정말 감사합니다 ㅠㅠ!!

  6. phalanx89 2014.10.21 12:12 신고

    감사합니다!
    아쉬운건 getDrawingCache가 왜 안되는지.. 저도 못찾겠더라구요 ㅠ

  7. 양창엽 2014.12.22 09:55 신고

    와 진짜 감사합니다 ㅠㅠ
    저도 용량이 작은 파일 들은 잘 되는데 어느 순간 용량이 큰 파일 들은 안되는 거에요 ㅠㅠ 그래서 진짜 화딱지 많이 났는데 여기서 해답의 열쇠를 찾다니 ㅠㅠ 감사합니다.
    보니깐 이걸 미리 해놓으면 좋은거 같아요. 미리 그려 놓고 바로 저장 하는 거 아닌가요 ㅠㅠ 암튼 감사합니다.
    제 블로그에 퍼가도 되죠 ㅠ?
    그리고 한가지 더 질문 좀 해도되나요?
    Bitmap.Config.ARGB_8888 무슨 뜻인지 알 수 있을까요?

    • yonoo88 2014.12.22 10:08 신고

      넴 출처만 적어주시면 퍼가셔도 됩니다. 멘붕에 빠진 사람들을 구제합시다! 저도 엄청 짱났었어요.

      그리고 저도 복붙유저라 잘은 모르지만...

      ARGB_8888는 이미지 품질?이라고 보시면 되거든요

      16Bit Bitmap : #RRRRRGGGGGGBBBBB (RGB_565)
      24Bit Bitmap : #RRRRRRRRGGGGGGGGBBBBBBBB (RGB_888)
      32Bit Bitmap : #AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB (ARGB_8888)

      이런 설명이 있는데 확실한 건 ARGB_8888 이게 품질이 제일 좋은거네요 ㅋㅋ

  8. anter 2015.01.05 17:58 신고

    you save my day!!2 ..
    제일 어려운 문제를 가장 쉽게 풀었네요.. 감사합니다.. ^^

  9. 마파로스 2015.10.15 20:50 신고

    저같은 경우는 핵심코드 부분이 없었을때도 잘 되었는데 어느때 부터 안되기 시작해서 해당 코드를 적용했더니 해결이 되네요..아마도 캔버스 사이즈에 관련된 오류라고 생각합니다.거길 변경한후 안되기 시작하더군요.하지만 해당코드를 적용하니 당연히 해결이 됩니다.그리는 거니까.

    • yonoo88 2016.01.18 17:09 신고

      아 다행이네요 사이즈가 넘친건지 그게 문제가 될 수도 있는거군요..

  10. 지나가는 프로그래머 2016.01.18 16:57 신고

    너무 감사합니다 ㅜ.ㅜ 스크린 캡쳐가 구연안되서 엄청 골탕먹었는데 감사합니당

  11. 왕초보 2017.09.02 10:15 신고

    글잘읽었습니다 그런데 도무지 이해가 안되서요 ㅜ ㅜ 실례가안된다면 죄송하지만 소스좀 얻을수있을까요?

  12. jhkim7559 2018.04.11 20:49 신고

    혹시 홈화면같은 현재화면 캡쳐는 하는 방식도 알고 계신가요..?

+ Recent posts

티스토리 툴바