반응형

Error와 Exception... 에러와 예외...

Error와 Exception은 같다고 생각할 수도 있지만, 사실 큰 차이가 있다.

- Error : 컴파일 시 문법적인 오류와 런타임 시 널포인트 참조와 같은 오류로 프로세스에 심각한 문제를 야기 시켜 프로세스를 종료 시킬 수 있다.

- Exception : 컴퓨터 시스템의 동작 도중 예기치 않았던 이상 상태가 발생하여 수행 중인 프로그램이 영향을 받는 것. 예를 들면, 연산 도중 넘침에 의해 발생한 끼어들기 등이 이에 해당한다.

  프로그램이 실행 중 어떤 원인에 의해서 오작동을 하거나 비정상적으로 종료되는 경우를 프로그램 오류라 하고, 프로그램오류에는 에러(error)와 예외(exception) 두 가지로 구분할 수 있다. 에러는 메모리 부족이나 스택오버플로우와 같이 발생하면 복구할 수 없는 심각한 오류이고, 예외는 발생하더라도 수습할 수 있는 비교적 덜 심각한 오류이다. 이 예외는 프로그래머가 적절히 코드를 작성해주면 비정상적인 종류를 막을 수 있다.

  Error의 상황을 미리 미연에 방지하기 위해서 Exception 상황을 만들 수 있다. java에서는 try-catch문으로 Exception handling을 할 수 있다.

반응형
반응형

특정 요일을 선택했으면 선택한 요일에 대해서만 알람을 울리고 선택된 요일이 없으면 설정된 시간에 한번만 알람이 울리도록 합니다. 전체적인 코드는 블로그에 올려두기 보다는 그냥 했던 방법을 적어 둘려고 합니다.


//알람 등록 및 취소

	private void registAlarm()
	{
		cancelAlarm();
		
		boolean[] week = { false, mTextRepeatSun.isSelected(), mTextRepeatMon.isSelected(), mTextRepeatTue.isSelected(),
				mTextRepeatWed.isSelected(), mTextRepeatThu.isSelected(), mTextRepeatFri.isSelected(),
				mTextRepeatSat.isSelected() };
		
		boolean isRepeat = false;
		int len = week.length;
		for (int i = 0; i < len; i++)
		{
			if (week[i])
			{
				isRepeat = true;
				break;
			}
		}

		// 알람 등록
		Intent intent = new Intent(this, AlarmReceiver.class);
		
		long triggerTime = 0;
		long intervalTime = 24 * 60 * 60 * 1000;// 24시간
		if(isRepeat)
		{
			intent.putExtra("one_time", false);
			intent.putExtra("day_of_week", week);
			PendingIntent pending = getPendingIntent(intent);
			
			triggerTime = setTriggerTime();
			
			mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, intervalTime, pending);
		}
		else
		{
			intent.putExtra("one_time", true);
			PendingIntent pending = getPendingIntent(intent);
			
			triggerTime = setTriggerTime();
			mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, pending);
		}
		
		showToastMessage(getString(R.string.alarm_time_set_toast));
	}

	private PendingIntent getPendingIntent(Intent intent)
	{
		PendingIntent pIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
		return pIntent;
	}
	
	private void showToastMessage(String message)
	{
		if(mToast == null)
		{
			mToast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
		}
		else
		{
			mToast.setText(message);
		}
		mToast.show();
	}
	
	private long setTriggerTime()
	{
		// current Time
		long atime = System.currentTimeMillis();
		// timepicker
		Calendar curTime = Calendar.getInstance();
		curTime.set(Calendar.HOUR_OF_DAY, this.mAlarmData.getHour(this));
		curTime.set(Calendar.MINUTE, this.mAlarmData.getMinute(this));
		curTime.set(Calendar.SECOND, 0);
		curTime.set(Calendar.MILLISECOND, 0);
		long btime = curTime.getTimeInMillis();
		long triggerTime = btime;
		if (atime > btime)
			triggerTime += 1000 * 60 * 60 * 24;
		
		return triggerTime;
	}

	private void cancelAlarm()
	{
		Intent intent = new Intent(this, AlarmReceiver.class);
		PendingIntent pending = getPendingIntent(intent);
		this.mAlarmManager.cancel(pending);
	}


//AlarmReceiver

public class AlarmReceiver extends BroadcastReceiver
{
	@Override
	public void onReceive(Context context, Intent intent)
	{
		Bundle extra = intent.getExtras();
		if (extra != null)
		{
			boolean isOneTime = extra.getBoolean("one_time");
			if (isOneTime)
			{
				AlarmDataManager.getInstance().setAlarmEnable(context, false);
                                // 알람 울리기.
			}
			else
			{
				boolean[] week = extra.getBooleanArray("day_of_week");

				Calendar cal = Calendar.getInstance();

				if (!week[cal.get(Calendar.DAY_OF_WEEK)])
					return;

                                // 알람 울리기.
			}
		}
	}
}


저는 이와 같이 만들어서 사용합니다.


반응형
반응형

  Android 의 ListView에서 하나의 Item이 변경이 되면 해당 Item에 대한 dataset을 변경 후 화면에 보이는 내용을 변경해 주어야만 합니다. 그리고 나서 보통 adapter에 있는 notifyDataSetChanged()라는 메소드를 호출하여 화면에 보이는 내용을 변경합니다. 

  하지만 이 방법에는 작은 단점이 있습니다. adapter에 있는 notifyDataSetChanged()메소드를 호출하게 되면 화면에 보이는 모든 ListView의 Item에 대하여 화며을 변경하게 됩니다. 즉 화면에 ListView의 Item이 5개가 있다면 5개 전부 다 다시 그려지게 됩니다. adapter에 있는 data중 하나만 변경되었지만 adapter에서는 어떤 item의 dataset이 변경되었는지 알 수 없으니까요.

  그럼 ListView의 single item에 대해서 변경된 내용을 적용하는 방법이 없을까요? 간단한 방법으로 해결 할 수 있습니다. 변경하고자 하는 View를 ListView의 메소드인 getChildAt(int index) 를 통해서 변경하고자 하는 View를 가지고 올 수 있습니다. 

public View getChildAt (int index)

Added in API level 1

Returns the view at the specified position in the group.

Parameters
indexthe position at which to get the view from
Returns
  • the view at the specified position or null if the position does not exist within the group

변경하고자 하는 index를 알지만 현재 화면에 보이는 ListView의 item에 대해서는 index를 어떻게 확인할까요?  AdapterView의 메소드 중 현재 화면에 보여지는 ListView의 첫번째 Item이 전체 몇번째 index인지를 알려주는 메소드가 있습니다. getFirstVisiblePosition()을 통해서 알 수 있습니다.

public int getFirstVisiblePosition ()

Added in API level 1

Returns the position within the adapter's data set for the first item displayed on screen.

Returns
  • The position within the adapter's data set


그럼 이 두 메소드를 통해서 간단하게 TextView의 내용을 변경해 보도록 하겠습니다.


private void updateSingleItemView(int position)
{
    int firstVisiblePosition = mListView.getFirstVisiblePosition();
    View view = mListView.getChildAt(position - firstVisiblePosition);
    TextView textTitle = (TextView)view.findViewById(R.id.text_title);
    textTitle.setText("Title Change");
}

이와 같은 방법으로 변경하고자 하는 하나의 아이템에 대해서 내용을 변경 할 수 있습니다.

하지만 이 방법은 지금 보이는 화면에View에 대한 변경된 내용이 지속도지 않습니다. 지속되게 할려면 이전에 먼저 꼭 dataset을 먼저 변경해 주시기 바랍니다. 그리고 난 뒤에 single item에 대해서 내용을 변경해야 합니다. 그 후 ListView를 scroll한다든지에 따라서 Adapter의 View getView (int position, View convertView, ViewGroup parent) 에 의해서 화면이 다시 그려질 때 dataset이 변경되어 있지 않다면 이전의 내용으로 보이게 될 것입니다.

반응형
반응형




Android 4.0 ICS 이상 부터 음악을 듣다보면 기본 런처의 lock  화면에서 이와 같이 음악을 컨트롤 할 수 있는 기능을 확인할 수 있을 것입니다. 이 기능을 활용하기 위해서는 

RemoteControlClient(http://developer.android.com/reference/android/media/RemoteControlClient.html) 를 이용하여 사용할 수 있습니다. Added in API level 14 라는건 확인하셔야 하구요.

Developer 페이지 설명을 보아도 사용 할 수 있도록 잘 설명이 되어 있습니다. 주의사항도 적혀 있구요.

A remote control client object is associated with a media button event receiver. This event receiver must have been previously registered withregisterMediaButtonEventReceiver(ComponentName) before the RemoteControlClient can be registered throughregisterRemoteControlClient(RemoteControlClient).

이와 같은 내용도 있지만. 이외 별도로 AudioFocus를 가지고 있어야 합니다.

AudioManager의 requestAudioFocus()메소드를 통해서 현재 플레이어에 AudioFocus가 있어야지 기본 런처의 lock화면에 이와 같은 음악 컨트롤 할 수 있는 화면이 나오게 됩니다.

등록하는 부분.

private void registerRemoteClient()
	{
		if (Build.VERSION.SDK_INT >= 14)
		{
			try
			{
				if (mAudioManager == null)
				{
					mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
				}
				Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
				mRemoteComponent = new ComponentName(this, AudioPlayerRemoteEventReceiver.class.getName());
				mAudioManager.registerMediaButtonEventReceiver(mRemoteComponent);
				mediaButtonIntent.setComponent(mRemoteComponent);
				mediaButtonIntent.setComponent(mRemoteControlResponder);
				PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);

				myRemoteControlClient = new RemoteControlClient(mediaPendingIntent);
				mAudioManager.registerRemoteControlClient(myRemoteControlClient);

				myRemoteControlClient.setTransportControlFlags(RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
						| RemoteControlClient.FLAG_KEY_MEDIA_STOP
						| RemoteControlClient.FLAG_KEY_MEDIA_NEXT
						| RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS
						| RemoteControlClient.FLAG_KEY_MEDIA_PLAY
						| RemoteControlClient.FLAG_KEY_MEDIA_PAUSE);
			}
			catch (Exception e)
			{
				if(CNCronosLog.isDebugLevel())
				{
					e.printStackTrace();
				}
			}
		}
	}

unregister

	private void unregisterRemoteClient()
	{
		try
		{
			if (Build.VERSION.SDK_INT >= 14)
			{
				if(mRemoteComponent != null)
				{
					mAudioManager.unregisterMediaButtonEventReceiver(mRemoteComponent);
					mRemoteComponent = null;;
				}
				if (myRemoteControlClient != null)
				{
					mAudioManager.unregisterRemoteControlClient(myRemoteControlClient);
				}
			}
		}
		catch (Exception e)
		{
			if(CNCronosLog.isDebugLevel())
			{
				e.printStackTrace();
			}
		}
	}

기본 lock 화면에다가 정보 보내는 부분.

					MetadataEditor metaEdit = myRemoteControlClient.editMetadata(true);
					
					metaEdit.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, "title");
					metaEdit.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, "artist");
					metaEdit.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, "album");
					metaEdit.putBitmap(MetadataEditor.BITMAP_KEY_ARTWORK, bitmap);
					metaEdit.apply();


현재 player 상태 보내는 부분.

						myRemoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
						myRemoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
						myRemoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
						myRemoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);
						myRemoteControlClient.setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED);


이와 같이 사용하면 원하는 상태로 기본 런처의 lock 화면에 음악재생의 컨트롤을 활용할 수 있을 것입니다.


반응형
반응형

이전 사용하던 마우사를 오래 사용하기도 했고, 바꿀 때가 되기도 해서 알아보던 중

MadCatz RAT7을 살 까 고민하던 중에 로지텍에서 새로운 마우스가 출시한다고 해서 RAT7을 살려던 것을 접고 이 제품을 기다리기 시작 했습니다.

MadCatz 제품의 특징이라면 마우스 부분 파츠를 자기 손에 맞게 직접 위치를 바꿀 수 있겠죠. 그런데 국내 정식수입제품을 사기엔 가격이 아마존에서 사는 것보다 너무 차이가 많이 나서... 사실 RAT7을 아직도 아마존에서 살까 말까 하는 고민은 계속 하고 있긴 합니다..

예약구매를 진행하고. 5월 19일부터 배송 시작한다고 해서 이제서야 받아서 개봉을 해봅니다.

박스모양.


박스 개봉전 마우스 모양을 확인해봄.


내용품. 마우스와 무개추가 들어있는 박스.

연결 시 LED가 들어옴..


무게추를 하나도 안넣고 사용하면 너무 가볍고.

다 넣고 사용하면 괜찮긴 하지만 오래 사용하면 팔목이 아픈듯?? 하기도 하고.. 적당한 무개를 찾아봐야 할 듯 합니다.

무게추 하나당 3.6 그램이니...


음.. 하지만 개발자로서 마우스보다 키보드를 더 많이 사용한다는 것이.. 함정! ^^



반응형

'사용기' 카테고리의 다른 글

Anker® 40W 5V / 8A 5-Port 충전기.  (0) 2014.02.21
REALFORCE 87U 구입 (realforce 87u all-45 EK Edition  (2) 2014.02.07
로지텍 G-700  (0) 2011.08.14
반응형

안드로이드 개발을 하다 보면 지금보다 조금 더 성능을 낼 수 있는 앱을 만들고 싶어질 때가 있습니다. 개발자 마다 코딩 스킬도 틀리고 더군다나 디바이스마다 스펙도 틀리기 때문에 같은 앱을 누가 만드느냐 어떤 디바이스에서 동작하느냐에 따라서 앱의 performance가 틀리게 나옵니다. 디바이스 스펙은 어쩔 수 없지만 개발하는 중간중간 조금의 신경을 쓴다면 성능이 좋은 앱을 만들 수 있을 거라 생각 됩니다. 안드로이드 앱을 개발하면서 경험했던 내용에 대해서 조금 정리를 해볼려고 합니다.


■ Traceview Profiling (http://developer.android.com/tools/debugging/debugging-tracing.html)

자신이 개발한 메소드 안에서 수행시간이 얼마나 걸리는지 알아보고, 수행 시간이 많이 걸렸다면 그만큼 performance에 영향을 줍니다. 그중에서 Android SDK 에 포함되어 있는 Traceview라는 것이 있습니다. 각 메소드에 대해서 프로파일링 한 결과를 그래픽으로 보여주는 좋은 툴입니다. 하지만 처음 사용하면 이게 뭐지?? 라는 생각을 가지고 있는 좀 복잡해 보이기도 합니다. 


그림과 같이 "Start Method Profiling" 버튼을 클릭 후 앱을 동작시킵니다. 그럼 동작되는 동안 수행되는 메소드에 대해서 프로파일링을 진행합니다. 그리고 나서 같은 위치에서 모양이 바뀐 "Stop Method Profiling" 버튼을 클릭 하고 나면 프로파일링이 끝난 결과를 화면에 보여 줍니다.

딱 이그림이 처음 보면... 뭐 이리 복잡해?? 라는 생각을 갖게 하는 그림 입니다. 

표의 내용은.

 - Incl Cpu Time % / Incl CPU Time : 해당 메소드 및 그것이 호출하는 자식메소드를 포함한 CPU의 수행 시간.

 - Excl Cpu Time % / Excl CPU Time : 메소드가 수행된 CPU 시간

 - Incl Real Time %/ Incl Real Time : 해당 메소드 및 그것이 호출하는 자식 메소드를 포함한 실제 시간.

 - Excl Real Time % / Excl Real Time : 메소드가 수행되는 실제 시간.

 저는 이중에서 Excl Real Time% / Excl Real Time 을 중요하게 봅니다. 해당 표의 값이 높으면 다른 Excel cpu time 이나 incl real time 도 높게 나타날 것입니다. 해당 부분을 클릭 하면 아래로 더 자세한 내용이 나옵니다. 저는 테스트하기 위해서 AsyncTask에서 String의 조합을 강제로 10000회 하도록 했습니다. 전체 프로파일링 중에 대부분 해당 부분에서 수행시간이 많이 나왔습니다.

설명은 DDMS를 이용한 방법을 설명했지만 직접 trace 파일을 생성해서 traceview로 보는 방법도 있습니다. 그건 Android 개발자 페이지에 더 자세하게 나와있으니 잠깐이라도 봐보시기 바랍니다.

■ GUI Optimization

http://developer.android.com/tools/debugging/debugging-ui.html

1. Hierarchy Viewer

Hierarchy Viewer 현재 화면에 보여지는 layout에 대하여 Tree View 형태로 보여주며 개발자가 UI 인터페이스를 디버깅 하고 분석할 수 있도록 도와 주는 도구 입니다. 각 component에 대해서 소비 시간을 분석과 다른 component와 비교도 할 수도 있고 각각의 속성도 파악 합니다. 그리고 해당 component가 어떤 화면인지에 대해서도 볼 수 있습니다.

그림과 같이 화면에 대한 분석화면을 볼 수 있고,


이와 같이 각 component에 대해서 분석한 화면도 볼 수 있습니다.맨 하단에 있는 Measure, layout, and draw performance indicators for this view에 나온 녹색, 노란색, 빨간색 원을 볼 수 있는데 녹색>노란색>빨간색 순으로 좋다고 보시면 됩니다. 그런데 해당 component에 대해서 무조건 녹색을 만들기는 어려워 보입니다. layout의 depth가 깊어지면 제일 상위에 있는 layout에 대해서는 녹색보다는 노란색과 빨간색을 더 많이 보여줍니다. 그래서 부모쪽 보다는 최 하단에 있는 자식 layout과 그에 해당하는 component에 대해서 최적화를 많이 합니다. 그러다 보면 상위로 갈 수록 빨간색과 노란색 보다는 녹색의 비율이 더 많아지더군요.


 - Lint warnings : Android resource(layout. string 등등)을 검사하여 잠재적으로 오류를 나타낼 수 있는 부분에 대하여 미리 검사를 합니다. 실행에는 전혀 문제가 없지만 경고가 잠재적인 오류를 가지고 있기 때문에 확인해 볼 필요는 있습니다.

 - layoutopt : layout의 xml 파일에 대해서 분석하여 비효율적인 부분에 대해서 알려주는 console tool.

Lint Warnings와 layoutopt에 제가 보는 것은 layout의 depth입니다. 지금 layoutopt는 android sdk tool에서 보이지 않습니다. 언제 사라진 것인지도 잘 모르겠습니다. 그래서 요즘은 Lint Warnings를 통해서 layout을 확인합니다. xml에서 layout을 만들고 lint warnings로 확인하다 보면 가끔 

이와 같이 "This RelativeLayout layout or its LinearLayout parent is useless"라는 메시지를 보이는 곳이 있습니다. RelativeLayout이나 LinearLayout은 경우에 따라 달라질 수도 있습니다. 쉽게 현재 사용중인 layout의 부모 layout은 쓸모가 없다는 내용입니다. 저는 이런게 보이면 과감하게 현재보다 바로 윗단계이 있는 layout에 대해서는 과감하게 삭제 합니다. 적어도 쓸모가 없기 때문입니다. Layout 의 Depth를 적게 하면 할수록 화면을 그리는 UI Thread의 작업이 조금이나마 줄어들것입니다. 작업이 줄어들 수록 수행 속도가 빠르다는 것도 다들 알 것이구요. 

제가 경험한 것으로는 한 화면에 너무 많은 컴포넌트들을 보여주고 싶어하는 디자이너와 기획자의 요구에 따라서 화면을 구성하다 보니 많은 layout을 사용하게 되었습니다. 단방향으로 고정된 화면에서 문제가 없었지만, 수많은 layout과 depth가 깊은 화면에 대해서 Animation을 수행할 때와 layout/layout-land 로 구성된 화면에서 screen rotaton을 하여 portrait과 landscape 화면에 대하여 서로 다른 화면을 구성할 때 문제가 되었습니다. 그래서 가급적이면 화면을 구성할 때 layout의 depth를 적게 하라고 권하고 싶습니다.


■ GC(Garbage Collection)

Android 는 디바이스마다 Heap 크기도 틀리고 하다 보니.. 메모리 관리도 중요하다고 할 수 있죠. Java의 GC(Garbage Collection)만 얘기도도 너무나 많으 내용이 될듯 싶고, 찾압면 정말 자세하게 설명해둔 자료들도 많으니 따로 찾아보셔도 될듯 합니다. 앱 개발하면서 메모리를 얼마나 많이 사용 되고 있는지 확인해볼 방법은 여러가지가 있겠지만 전 두가지를 알려드릴려고 합니다. DDMS에 있는 "Allocation Tracker"와 Heap dump 파일 분석을 통해 알아볼까 합니다.

- Allocation Tracker

DDMS에서 확인하고 싶은 앱 선택 후 Allocation Tracker에서 Start Tracking 클릭 후 GetAllocations를 누르면 현재 메모리가 할당된 Object들의 목록이 나타납니다. Allocation Size를 제일 많이 차지하고 있는 항목을 선택하고 나면 두번째 테이블에는 해당 Object의 Stack Trace 정보가 출력됩니다. 만약 해당 Allocation Size가 비정상적으로 많다면 해당 방법으로 잘못된 곳을 찾을 수도 있을것입니다.

- HPROF

힙덤프 파일을 생성해서 분석해볼 수도 있습니다. 힙덤프 생성하는 방법은 adb를 이용하거나 api를 이용. 또 DDMS를 이용해서 할 수 있습니다.

1. ADB 이용

$ adb shell

# mkdir /data/misc

# chmod 777 /data/misc (/data/misc에 쓰기권한 확인)

# ps (애플리케이션 프로세스 ID 확인)

# kill -10 <pid> (SIGUSR1 시그널 전송)

(잠시후 /data/misc 에 heap-dump-*.hprof 파일 생성됨)

$ adb pull <dump-file> <as-file> (로컬로 파일 추출)

ADB shell을 이용할려면 root 권한이 있어야 하고.. 매번 이런식으로 shell 접속하기 귀찮아서 잘 사용 안합니다. ㅡㅡ.

2. API 이요

android.os.Debug.dumpHprofData(fileName);

- fileName의 위치는 쓰기 권한이 있는 곳이어야 합니다. 외장메모리 영역이면 괜찮겠죠? 대신 WRITE_EXTERNAL_STORAGE permission 지정을 잊지 않으시면 됩니다.

3. DDMS 이용.

가장 현실적인 이용방법입니다. adb shell을 일일이 드어가기 귀찮고. 그렇다고 api를 이용하면 앱 release 시에는 해당 부분을 삭제 해 줘야 하기도 하고. 그리고 해당 heap dump 파일을 분석해주는 Eclipse MAT라는 plugin도 있습니다.


Dump HPROF file 버튼을 클릭 합니다. 저가은 경우는 Eclipse MAT플러그인을 상용하는 관계로 바로 아래와 같은 그래픽컬한 화면이 나옵니다. 바로 dump된 파일을 분석해서 그래프로 보여주는 것이죠. 

Shallow Heap과 Retained Heap을 통해서 어디서 메모리 누수가 발생하는지 확인을 할 수 있습니다.

Shallow Heap : 객체 하나당 크기.

Retained Heap : 참조가 유지하고 있는 모든 객체의 크기.

만약 상위  " Retain Heap < 하위 Retain Heap + 모든 Shallow Heap "  으로 나온다면 계산하고 있는 하위 객체에 대해서 메모리 누수가 발생하고 있다고 보면 됩니다.


이외에도 WakeLock을 어떻게 사용하느냐에 따라서 앱 전체 성능에 영향이 있을 수도 있습니다.

이 방법들 이외에도 다른 방법들도 많으 것으로 보입니다. 그런데 이런것으로 확인하는 것도 좋지만, 개발자가 개발할 당시에 조금이라도 신경써서 하면 개발한다면 좋은 성능을 낼 수 있는 앱을 만들 수 있겠죠. 개발이 완료되어 앱이 릴리즈 되었다면 개발되었던 것을 다시 돌아보면서 리펙토링 하는 시간도 갖는다면 좋을 것이구요. 하지만 현실은 그렇지 않아 보입니다. 현실은 하나 완료하기도 전에 다음 업데이트 일정들이 나오고 있으니까요.





반응형
반응형

5port usb 충전기로 Anker 충전기가 유명하죠.

이전에 White 모델은 25W여서는 port 별로 충전할 수 있는 디바이스가 정해져 있었으나 40W 제품은 이런 단점이 없습니다. 그리고 지금은 White 모델도 40W 로 나온 모델도 있습니다. 제가 구매했을 때 40W로는 블랙 제품밖에 없었죠. 40W와 25W는 가격차이가 있는데 싼거 사겠다고 25W 충전기 구매하면 후회할 수 있습니다 

Amazon에서 구매하고 배대지 통해서 물건을 받았습니다.


박스는 이렇게... 


물건은 이렇게 들어있네요. 설명서도 있지만 pass~

프리볼트입니다. 전원케이블이 110v용 이긴 하지만. 220v 용 돼지코나 220v용 8자 케이블 이요하면 됩니다. 저는 220v용 8자 케이블 구매해서 사용중입니다.

우선 3개 연결해서 충전하고 있습니다.

개발하다보면 가끔 테스트폰들을 충전안시켜서 바로 테스트 못할 때도 있는데.. 머 이렇게 하니 이런저런 문제는 해결되네요. 그리고 2개 구매해서 하나는 집에서 하나는 회사에서 사용 중입니다. 집에서 와이프와 제폰.. 그리고 아이팟터치 이외에 몇몇 기기들 충전용으로 만족하며 사용중~





반응형

'사용기' 카테고리의 다른 글

로지텍 G502 PROTEUS CORE 마우스  (0) 2014.05.21
REALFORCE 87U 구입 (realforce 87u all-45 EK Edition  (2) 2014.02.07
로지텍 G-700  (0) 2011.08.14
반응형

정전용량무접점...

키보드 사용자들에게선 이 키축을 사용하는 키보드는 비싸고 꼭한번 사보고 싶은 키보드 일것 같습니다. 리얼포스나 해피해킹 프로페셔널 키보드가 그 종류중 하나 일 것 같습니다.

이전까지 잘 사용하고 있던 키보드는 필코 마제스터치 기계식 키보드 입니다. 갈축으로 넌클릭 제품이죠. 그런데 기계식 키보드를 사용하면 주변분들의 반응은 다 이런 반응들 입니다. "시끄러운데???" 처음 기계식 키보드를 구입할 때 청축 클릭제품을 사용하고 싶었지만 너무 시끄러울 것 같아서 갈축을 산것이였는데 ㅎㅎ


해피해킹 프로페셔널 키보드 자체도 비싸서... 구입 할 때 큰마음 먹고 구입했어야 했는데 이번 리얼포스 구입하는 것도 정말 큰마음을 먹어야 하는군요. 가격이 L모 사이트에서 구입하면 36만원의 가격을 줘야 구입할 수 있으니까요. 하지만 아쉽게도 L모 사이트나 국내 다른 리얼포스 판매하는 곳에서는 제가 원하는 all-45g 모델이 없습니다 ㅡㅡ... 55g 모델이나 차등 모델은 있지만..  차등은 왠지 별로?? 일듯 싶고, 55g 균등은 무거울 거 같더군요... 기계식 갈축이 45g정도의 무게를 가지고 있고 집에서 사용하는 해피해킹 프로페셔널도 45g의 무게이니 적응하기 편한 45g 균등 리얼포스가 가지고 싶어졌습니다. 그래서 구글링 해서 찾은 곳이 해외 elitekeyboard 라는 곳입니다. 제가 원하는 all-45g의 균등 키보드를 판매하고 있더군요. 


원하는 제품을 판매하는 곳을 찾았지만 바로 구매를 하지 못하고 망설인 시간도 있었습니다. 첫번째 이유는 거금을 들여서 키보드를 구입하고자 하니 와이프의 눈치가 보이고, 더군다나 elitekeyboard라는 곳이 믿을만한 곳인가?? 라는 두가지 이유입니다. 와이프 허락을 받았지만 elitekeyboard가 정말 믿고 구입할 곳인지에 대한 검증도 필요하구요. 고민고민 한 이유중 하나도 해당 사이트는 회원가입을 통한 구입이 아니기도 하니.. add cart 한다음 결제를 할까말까 고민고민 하고 매일 사이트에 들어가서 지켜보기도 하고... 그런데 처음 $239 하던 가격이 $199로 super sale!! 을 하게 된것입니다. 처음 지켜보던 가격에서 무려 $40 이나 내려간 가격!!!!! 머 구글링해서 얻은 정보로는 elitekeyboard에서 구입한 몇몇 분들은 2주정도 기다려서 잘 받았다고 후기들이 있기에 사기당하면 비싼 직배경험 공부 비용으로 지불했다는 마음을 가지고 배송비 $65 정도 해서 구입했습니다. 그리고 나서 다음날 결제완료되었으니 2일안에 발송하면 트랙킹 정보를 보내주겠다는 메일이 왔고 다행히 2일뒤 USPS로 발송했다는 트랙킹 정보 메일을 받았습니다. 이제부터 리얼포스를 기다리면 됩니다.


그런데 1주일만에 키보드가 도착했습니다. 상당히 빨리 오더군요. 



REALFORCE 87U All-45 모델입니다 ㅎㅎ


6년여 동안 저의 개발인생을 같이해온 필코 마제스터치와 방금 개봉한 realforce 87u all-45 모델이죠. 누군가는 이걸 보고 필코가 초라해 보인다고 했지만 아직까지 필코도 현역입니다 ㅎㅎ.. 좀 험하게 다루기도 했고(코딩할 때 키보드를 부셔버릴 듯이 사용했으니 ㅎㅎ) 키캡 여러부분들이 벗겨져서 구각처럼 된 곳도 있고.. 하지만 정이 많이 가는 키보드 입니다.


그리고 따로 또 구입한 키보드 루프 입니다. 키보드 사이사이에 먼지 쌓이게 하고 싶지 않아서 주문제작?? 한 것이죠. 정품 리얼포스 루프는 가격이 비싸죠. 약 4만원정도 하는데.. 사실 아크릴 엎개를 그정도 갚을 주고 사기엔 많이 아까워서. 그래서 아크릴 가공하는 곳에 치수를 보내면 저렇게 만들어서 보냅니다. 가격은 정품의 1/3 가격! 투명한 것도 있지만 그냥 사진과 같은 불투명으로 구매!!


키보드 루프를 덮어둔 모습입니다. 은근 괜찮네요 ㅎㅎ



앞으로 저와 언제까지??? 할지 모르겠지만 

몇일간 사용한 소감은... 한번쯤은 사용해볼만한 것 같습니다. 우선 해피해킹 프로페셔널과 같은 정전용량무접점인것! 키감은 나쁘지 않지만 개인적으로 100% 만족스럽지도 않습니다. 워낙 기계식을 오래?? 써서 그런듯 싶기도하구요^^ 이러다 더 적응되면 나중엔 기계식으로 다시 갔을 때 적응하지 못하는거 아닌지도 모르겠습니다. 기계식에서 느껴지는 탁탁탁 그런 느낌보다는 사각사각 느낌이고... 이왕 산거 잘 사용해야지~

반응형

'사용기' 카테고리의 다른 글

로지텍 G502 PROTEUS CORE 마우스  (0) 2014.05.21
Anker® 40W 5V / 8A 5-Port 충전기.  (0) 2014.02.21
로지텍 G-700  (0) 2011.08.14

+ Recent posts