문제점

Dialog를 화면에 띄우려고할 때, 발생하는 에러.

BadTokenException: Unable to add window -- token null is not for an application

해결방안

대화상자 객체 생성시 파라미터를 확인할 것.

getApplicationContext()를 사용하지 말고, 액티비티명.this를 사용할 것

AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

에러 - the method setbackgrounddrawable(drawable) from the type view is deprecated

int sdk = android.os.Build.VERSION.SDK_INT;
if(sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
    setBackgroundDrawable()
} else {
    setBackground();
}

 실행환경

 Desktop

 조립식

 CPU

 Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz 3.40GHz

 Memory

 8.00 GB

 OS

 Windows 7 Professional K 64bit

 Java

 1.8.0_05

 MySQL

 Ver 14.14 Distrib 5.6.19, for Win64

Handler 사용하기

안드로이드에서는 메인스레드가 아닌 다른 스레드(백그라운드)에서 UI를 건들였을 때 에러가 발생한다. 이는 서로 변경하는 것을 허용하게 되면 동기화 문제가 발생하기 때문이다. 그렇기 때문에 핸들러(Handler)를 사용해서 스레드간에 통신을 할 수 있다.


방법 1

방법 2


방법 3


ListView에 Scrollbar 감추기

listview.xml

<ListView android:id="@+id/listview" ... android:scrollbars="none" >

ListView에 이동하는 스크롤바 적용하기(fast scroll)

listview.xml

<ListView android:id="@+id/listview" ... android:fastScrollEnabled="true" >


Application Specification

 Date

 2014.06.13

 Name

 wisay (wise saying)

 Version

 1.3.0

 minSdkVersion

 14

 비고

 .


v1.3.0 이전 업데이트

  • 1.0.0 - 텍스트 파일에 저장된 명언들을 구분자로 읽어 들여 리스트 출력 , 위젯기능
  • 1.0.1 - 디자인 수정(책상앞에 놓여있던 주황색 펜을 보고 주황색 선택)
  • 1.0.2 - 버튼 디자인 변경, 리스트에 각 명언 클릭시 Toast로 영어 번역 보기 기능
  • 1.0.3 - 버전 호환성 변경(minSdkVersion 변경)
  • 1.0.4 - 테스트용으로 올린 어플에서 사용자에게 필요한 부분 모두 지우고 재등록
  • 1.1.0 - 데이터를 텍스트파일에서 DB화, 리스트에 각 명언 클릭시 영어, 한글 함께보기 기능, 위젯 최대라인수 설정
  • 1.2.0 - 환경설정 추가(기본 언어 설정(영어, 한글)), 랜덤 명언 클릭시 영어, 한글 함께보기 기능 추가
  • 1.2.1 - 랜덤 명언 클릭시 새로고침 안되는것 수정, 사용 국가 추가(미국, 캐나다)
  • 1.3.0 - DB 구조 변경(카테고리 테이블 나눔), 카테고리 기능 추가, 데이터 추가


1. 변경 사항

DB 테이블 나누고 카테고리 기능을 추가하였다. 점점 클래스 구조가 복잡해지는 것 같다.


2. 보완해야할 점

검색기능, 즐겨찾기기능, 위젯 디자인 설정, 탭뷰 프래그먼트로 변경,

앞으로 업데이트할때마다 블로그에 남겨놔야겠다.

main.xml

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

    <TabHost
        android:id="@+id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1" >
            </FrameLayout>

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </TabHost>
</LinearLayout>

tabhost의 id가 @android:id/tabhost가 아닌 @+id/tabhost 이다.

위 tab은 FrameLayout 속성에 layout_weight="1" 때문에 하단에 위치하게 된다.


MainActivity.java

public class MainActivity extends ActivityGroup {
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		createTab();
	}

	private void createTab() {
		TabHost tabHost = (TabHost) findViewById(R.id.tabhost);
		tabHost.setup(getLocalActivityManager());

		tabHost.addTab(tabHost.newTabSpec("TAB1").setIndicator("TAB1")
				.setContent(new Intent(this, Tab1Activity.class)));
		tabHost.addTab(tabHost.newTabSpec("TAB2").setIndicator("TAB2")
				.setContent(new Intent(this, Tab2Activity.class)));

		}

	}
}


참고 사이트



어플리케이션 버전 가져오기

// 어플 버전 가져오기
PackageInfo pi = null;
try {
	pi = getPackageManager().getPackageInfo(getPackageName(), 0);
} catch (NameNotFoundException e) {
	Log.e(TAG, e.getMessage());
}
String appVersion = pi.versionName;
Int appCode = pi.versionCode; 


자바코드(activity)에서 setText()로 값 변경시 태그넣기

TextView t1 = (TextView)findViewById(R.id.t1);
t1.setText(Html.fromHtml("1번째줄" + "<br />" + "2번째줄"));


자바코드(or Activity)에서 string.xml 값 가져오기

String st1 = getString(R.string.s1);
CharSequence st2 = getText(R.string.s2);



자바캔에서 구현이 잘되어있어서 본문글 자체를 그래도 가져온 글입니다. 본문글은 이곳입니다.

(문제가 생긴다면 삭제하도록 하겠습니다.)


안드로이드에서 2회 연속 백버튼을 눌러서 앱을 종료시키는 경우가 흔한데, 이 기능은 많이 사용되므로 다음과 같이 별도 클래스로 기능을 분리하면 향후 기능 재사용이 편리하다.

public class BackPressCloseHandler {

	private long backKeyPressedTime = 0;
	private Toast toast;

	private Activity activity;

	public BackPressCloseHandler(Activity context) {
		this.activity = context;
	}

	public void onBackPressed() {
		if (System.currentTimeMillis() > backKeyPressedTime + 2000) {
			backKeyPressedTime = System.currentTimeMillis();
			showGuide();
			return;
		}
		if (System.currentTimeMillis() <= backKeyPressedTime + 2000) {
			activity.finish();
			toast.cancel();
		}
	}


	private void showGuide() {
		toast = Toast.makeText(activity, "\'뒤로\'버튼을 한번 더 누르시면 종료됩니다.",
				Toast.LENGTH_SHORT);
		toast.show();
	}

}

BackPressCloseHandler의 구현은 간단하다.

  • backKeyPressedTime은 백버튼이 눌린 마지막 시간을 기록한다.
  • onBackPressed() 메서드는 현재 시간이 마지막 백버튼 누른 시간으로부터 
    • 2초 이상 지났으면, 마지막 백버튼 눌린 시간을 현재 시간으로 갱신하고 showGuide()를 실행한다.
    • 2초 이상 지나지 않았으면, Activity를 종료한다.
    • 참고로, 2초는 Toast.LENGTH_SHORT의 기본 값이다.
  • showGuide() 메서드는 Toast를 이용해서 메시지를 출력한다.

2회 연속 백버튼 누를 때 종료시키고 싶은 Activity가 있다면, 다음과 같이 사용한다.

  • BackPressCloseHandler 타입의  backPressCloseHandler 필드를 추가한다.
  • onCreate() 메서드에서 BackPressCloseHandler 객체를 생성해서 필드에 할당한다.
  • onBackPressed() 메서드에서 backPressCloseHandler.onBackPressed()를 호출한다.
아래 코드는 실제 적용한 코드의 일부를 발췌한 것이다.


public class HomeActivity extends Activity ... {

	private BackPressCloseHandler backPressCloseHandler;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.home_layout);
		...
		backPressCloseHandler = new BackPressCloseHandler(this);
	}

	@Override
	public void onBackPressed() {
		backPressCloseHandler.onBackPressed();
	}
}


문제점

다이얼로그에서 버튼을 클릭하면 닫히는 것을 막으려고 한다. 
참고사이트

해결방안

기존 리스너는 버튼만 만들어주고 AlertDialog 객체를 통해 오버라이딩해서 사용한다. 
그리고 아래 조건문을 통해 dimiss()를 제어한다.

코드

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

		tvName = (TextView) findViewById(R.id.tvName);
		btnClick = (Button) findViewById(R.id.btnClick);

		btnClick.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				dialogView = (View) View.inflate(asdasd.this, R.layout.dialog,
						null);

				AlertDialog.Builder builder = new AlertDialog.Builder(
						asdasd.this);
				builder.setMessage("Test input data");
				builder.setView(dialogView);
				builder.setPositiveButton("ok",
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {
							}
						});
				builder.setNegativeButton("clear",
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {
							}
						});
				final AlertDialog dialog = builder.create();
				dialog.show();

				dlg_edt_name = (EditText) dialogView
						.findViewById(R.id.dlg_edt_name);

				dialog.getButton(AlertDialog.BUTTON_POSITIVE)
						.setOnClickListener(new View.OnClickListener() {
							@Override
							public void onClick(View v) {
								Boolean wantToCloseDialog = true;

								tvName.setText(dlg_edt_name.getText());

								if (wantToCloseDialog)
									dialog.dismiss();
							}
						});
				dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
						.setOnClickListener(new View.OnClickListener() {
							@Override
							public void onClick(View v) {
								Boolean wantToCloseDialog = false;

								dlg_edt_name.setText("");

								if (wantToCloseDialog)
									dialog.dismiss();

							}
						});
			}
		});
	}


dialogExam.zip


 실행환경

 Notebook

 SAMSUNG NT550p5c-s61r

 CPU

 Intel Core i5-3210M 2.50GHz

 Memory

 8 GB

 OS

 Window 7 ultimate 64bit

 Java

 1.8.0_05

 Android SDK : 4.4.2 (KitKat) / 테스트기기 : Galaxy S3 4.3 (Jelly Bean)

 WebServer

 Apache Tomcat 7.0

ImageButton Background 투명하게 만들기

위 사진과 같이 #00000000 로 변경한다.

API 이동

public final class PowerManager

java.lang.Object
-> android.os.PowerManager

Class Overview

이 클래스는 장치의 전원 상태를 제어할 수 있게 한다.


장치의 배터리 생명은 이 API를 사용함에 따라 상당한 영향을 받을 것이다. 정말로 필요하지 않는 한 acquire, PowerManager.WakeLock는 사용하지 말고, 가능한 가장 낮은 레벨을 사용하고 그리고 가능한 한 빨리 release하라.


너는 Context.getSystemService()를 호출함으로써 이 클래스의 인스턴스를 얻을수 있다. 


주된 API는 newWakeLock()이다. 그것은 PowerManager.WakeLock 객체를 만들어 준다. 너는 wake lock 객체를 이용해서 장치의 전원상태를 제어하는 메소드들 사용할 수 있다.


예)

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
    wl.acquire();
    // ..screen will stay on during this section..
    wl.release();


The following wake lock levels are defined, with varying effects on system power. 

그 다음으로 wake lock 레벨들은 시스템 전원에 변화하는 효과와 함께 정의된다. 이 레벨들은 상호 배타적이다. - 너는 오직 그것들 중 하나만 명시할지도 모른다.

Flag Value CPU Screen Keyboard
PARTIAL_WAKE_LOCK On* Off Off
SCREEN_DIM_WAKE_LOCK On Dim Off
SCREEN_BRIGHT_WAKE_LOCK On Bright Off
FULL_WAKE_LOCK On Bright Bright

*If you hold a partial wake lock, the CPU will continue to run, regardless of any display timeouts or the state of the screen and even after the user presses the power button. In all other wake locks, the CPU will run, but the user can still put the device to sleep using the power button.


덧붙혀, 너는 오직 화면의 행동에 영향을 주는 두개의 플래그를 추가할 수 있다. 그 플래그들은 PARTIAL_WAKE_LOCK와 같이 사용할때 효과를 얻지 못한다.

Flag Value Description
ACQUIRE_CAUSES_WAKEUP Normal wake locks don't actually turn on the illumination. Instead, they cause the illumination to remain on once it turns on (e.g. from user activity). This flag will force the screen and/or keyboard to turn on immediately, when the WakeLock is acquired. A typical use would be for notifications which are important for the user to see immediately.
ON_AFTER_RELEASE If this flag is set, the user activity timer will be reset when the WakeLock is released, causing the illumination to remain on a bit longer. This can be used to reduce flicker if you are cycling between wake lock conditions.

Any application using a WakeLock must request the android.permission.WAKE_LOCK permission in an <uses-permission> element of the application's manifest.


Summary

Nested Classes
class PowerManager.WakeLock A wake lock is a mechanism to indicate that your application needs to have the device stay on. 
Constants
int ACQUIRE_CAUSES_WAKEUP Wake lock flag: Turn the screen on when the wake lock is acquired.
int FULL_WAKE_LOCK This constant was deprecated in API level 17. Most applications should use FLAG_KEEP_SCREEN_ON instead of this type of wake lock, as it will be correctly managed by the platform as the user moves between applications and doesn't require a special permission.
int ON_AFTER_RELEASE Wake lock flag: When this wake lock is released, poke the user activity timer so the screen stays on for a little longer.
int PARTIAL_WAKE_LOCK Wake lock level: Ensures that the CPU is running; the screen and keyboard backlight will be allowed to go off.
int SCREEN_BRIGHT_WAKE_LOCK This constant was deprecated in API level 13. Most applications should use FLAG_KEEP_SCREEN_ON instead of this type of wake lock, as it will be correctly managed by the platform as the user moves between applications and doesn't require a special permission.
int SCREEN_DIM_WAKE_LOCK This constant was deprecated in API level 17. Most applications should use FLAG_KEEP_SCREEN_ON instead of this type of wake lock, as it will be correctly managed by the platform as the user moves between applications and doesn't require a special permission.
Public Methods
void goToSleep(long time)
Forces the device to go to sleep.
boolean isScreenOn()
Returns whether the screen is currently on. 화면이 현재 켜있는지 반환한다. 
PowerManager.WakeLock newWakeLock(int levelAndFlags, String tag)
Creates a new wake lock with the specified level and flags. 생성한다. 새로운 wake lock
void reboot(String reason)
장치를 재부팅한다.
void userActivity(long when, boolean noChangeLights)
Notifies the power manager that user activity happened.
void wakeUp(long time)
Forces the device to wake up from sleep.


Constants






http://aroundck.tistory.com/48



by the use of... -숙어- ...의 상용(일상적으로 씀)에 따라.

significantly -부사- (영향을 주거나 두드러징 정도로) 상당히[크게]

affected -형용사- 영향을 받은

unless -접속사- ......하지 않는 한

be sure to do something -숙어- (명령문으로 쓰여) 꼭[반드시] ~을 해라

as soon as -- ...하자마자

as soon as possible -숙어- 되도록 빨리

affect one's behavior -숙어- ~의 행동에 영향을 주다.

have no effect -숙어- 효과를 얻지 못하다


+ Recent posts