Linux 에서 adb devices 결과가 no permissions 인경우 해결방법.

Debian Lenny (5.0.3)에서 adb devices 를 했더니…

$ adb devices
List of devices attached
???????????? no permissions

검색을 해보니.. /etc/udev/rules.d/99-android.rules 에 디바이스 정보를 넣으라고 한다.
그러나.. 여전히 no permissions 이다.

좀더 찾아보니…

adb kill-server
adb start-server 를 root 권한으로 실행해보란다.

$ adb kill-server
$ adb start-server
* daemon not running. starting it now *
* daemon started successfully *
$ adb devices
List of devices attached
0403766B11005015 device

잘되네.. ㅡ.ㅡ

eclipse 에서도 application 실행도 잘 된다. :)

매번 저걸 넣기는 귀찮으니.. udev 에 룰을 등록하자.

먼저 장치가 연결될때 실행할 스크립트를 작성하자.

#!/bin/sh

TOOL_DIR=/home/eunchul/apps/android-sdk-linux_86/tools
${TOOL_DIR}/adb kill-server
${TOOL_DIR}/adb start-server

이 파일을 init_motoroi.sh 라 저장하고 적당한 디렉토리에 위치 시킨다. (나는 /home/eunchul/sbin/init_motoroi.sh)
이제는 udev 의 룰을 작성하자.

이 작업은 root 로 해야 한다.

# cd /etc/udev/rules.d
# touch 99-android.rules

99-android.rules 의 내용은..

# android
#

# motoroi
SUBSYSTEM==”usb”,ATTR{idVendor}==”22b8″,ATTR{idProduct}==”41db”,SYMLINK+=”motoroi_adb”,MODE=”0666″,RUN+=”/home/eunchul/sbin/init_motoroi.sh”

ATTR{idVendor} 과 ATTR{idProduct} 의 값은 lsusb 를 했을때 장치의 아이디 값이다.

# lsusb
Bus 007 Device 009: ID 22b8:41db Motorola PCS Motorola Droid (USB Debug)
Bus 007 Device 003: ID 05a9:2640 OmniVision Technologies, Inc. OV2640 Webcam
Bus 007 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 002: ID 0461:4d15 Primax Electronics, Ltd Dell Optical Mouse
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 004: ID 0a5c:4503 Broadcom Corp.
Bus 001 Device 003: ID 0a5c:4502 Broadcom Corp. Keyboard (Boot Interface Subclass)
Bus 001 Device 002: ID 0a5c:4500 Broadcom Corp. BCM2046B1 USB 2.0 Hub (part of BCM2046 Bluetooth)
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

이제는 udev 데몬을 재시작 해주면 된다.

# /etc/init.d/udev restart

이렇게 되면, usb 에 motoroi 가 연결이 될때마다 /home/eunchul/sbin/init_motoroi.sh 를 실행해준다.

참고: Developing on a Device, Nexus One Help Fourm

Posted in android, bash, debian, development, linux | Tagged , , , , , , | Leave a comment

Debian Lenny 의 Google Chrome 에 플래시 플러그인 추가하기.

XFS 파일시스템에 Debian Lenny 64bit 환경으로 잘 사용해오다가..
XFS 가 느린듯 하고, Android 개발을 위해서 i386 으로 돌아갈 필요가 있을것 같아서..
파티션을 나누고 Debian Lenny i386 으로 설치를 했고, 커널은 bigmem 으로해서 4GB 를 사용할 수 있게 했다.

그러고서 이것저것 설정을 하다가,
Google Chrome 설치까지 했다.
다 좋은데.. 플래시 플러그인을 어떻게 설치해야 모르겠다.
도무지 플러그인을 넣을만한 디렉토리가 보이지 않는것이다.

검색을 해보니… 그냥 만들란다.

Flash player 를 다운로드(install_flash_player_10_1_linux.tar.gz) 받고서 압축을 푼다.

# mkdir /opt/google/chrome/plugins
# mv libflashplayer.so /opt/google/chrome/plugins

그리고 크롬을 재시작 하고, 주소창에 “about:plugins” 를 입력해본다.
결과가 나오면 성공!!

Posted in debian, google-chrome | Tagged , , | Leave a comment

데이터를 처리하는 동안 progressDialog 표시하기.

Android 애플리케이션 개발에 관심이 있어서 간단한 프로그램을 만들어 보고 있다.
그러던중, xml 데이터를 읽어오보 ListView 로 출력하는 과정이 1~2초 정도 걸리는데..
뭔가 작업을 진행하고 있다고 표시해주는게 좋을듯 싶어 ProgressDialog 라는 녀석을 적용해보았다.

Creating a ProgressDialog 문서를 읽으면서 쉽게 될 것으로 예상했으나.. 생각보다 헤매였다.

문서상에는 되게 간단한 것으로 보여지지만,
Thread 와 Handler 를 이용해서 제어를 해야한다. (간단한건가…;;;)

package com.eunchul.zipcode;

import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class ZipcodeFinderActivity extends Activity {

	ListView zipcodeListView;
	ArrayAdapter zipcodeArrayAdapter;
	ArrayList zipcodes;

	ProgressDialog progressDialog;

	private Handler handler = new Handler();

	final private int PROGRESS_DIALOG = 0;
	final private int ZIPCODE_DIALOG = 21;
	Zipcode selectedZipcode;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //final EditText keyword = (EditText)findViewById(R.id.keyword);
        final Button searchButton = (Button)findViewById(R.id.search_button);
        zipcodeListView = (ListView)findViewById(R.id.zipcode_list_view);

        searchButton.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Thread thread = new Thread(null, getZipcodes);
				thread.start();
				showDialog(PROGRESS_DIALOG);
			}
		});

        zipcodeListView.setOnItemClickListener(new OnItemClickListener() {
        	public void onItemClick(AdapterView _av, View _v, int _index, long arg3) {
        		selectedZipcode = zipcodes.get(_index);

        		Log.d(this.getClass().getName(), selectedZipcode.getAddress());
        		Log.d(this.getClass().getName(), selectedZipcode.getZipcode());

        		showDialog(ZIPCODE_DIALOG);
        	}
        });

    }

    private Runnable getZipcodes = new Runnable() {
    	public void run() {
    		try {
		    	final EditText keyword = (EditText)findViewById(R.id.keyword);

		    	Log.d("getZipcodes", "executed...");

		    	ZipcodeFactory zf = new ZipcodeFactory();
		    	zipcodes = zf.search(keyword.getText().toString());

		    	handler.post(updateResults);

    		} catch (Exception e) {
    			Log.e("getZipcodes", e.toString());
    		}

    	}
    };

    private Runnable updateResults = new Runnable() {
    	public void run () {
	    	if (zipcodes != null) {
	    		Log.d("updateResults", "executed...");
		    	int layoutId = android.R.layout.simple_list_item_1;

		    	zipcodeArrayAdapter = new ArrayAdapter(ZipcodeFinderActivity.this, layoutId, zipcodes);
		    	zipcodeListView.setAdapter(zipcodeArrayAdapter);
	    	} else {
	    		showNotFoundZipcodes();
	    	}
    		progressDialog.dismiss();
    		ZipcodeFinderActivity.this.removeDialog(PROGRESS_DIALOG);
    	}
    };

    private void showNotFoundZipcodes() {
    	Toast toast = Toast.makeText(this, "Not found", Toast.LENGTH_SHORT);
    	toast.show();
    }

    @Override
    protected Dialog onCreateDialog (int id) {
    	switch (id) {
    	case (PROGRESS_DIALOG):
    		progressDialog = new ProgressDialog(this);
    		progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    		progressDialog.setMessage("Now loading..");
    		return progressDialog;

    	case (ZIPCODE_DIALOG):
    		LayoutInflater li = LayoutInflater.from(this);
    		View zipcodeDialogView = li.inflate(R.layout.zipcode_dialog, null);

    		AlertDialog.Builder zipcodeDialog = new AlertDialog.Builder(this);
    		zipcodeDialog.setTitle("Detail");
    		zipcodeDialog.setView(zipcodeDialogView);

    		return zipcodeDialog.create();
    	}
    	return null;
    }

    @Override
    protected void onPrepareDialog (int id, Dialog dialog) {
    	switch (id) {
    	case(ZIPCODE_DIALOG):
    		AlertDialog zipcodeDialog = (AlertDialog)dialog;

    		zipcodeDialog.setTitle(selectedZipcode.getZipcode());

    		TextView tvAddress = (TextView)zipcodeDialog.findViewById(R.id.dialog_address);
    		TextView tvZipcode = (TextView)zipcodeDialog.findViewById(R.id.dialog_zipcode);

    		tvAddress.setText(this.getString(R.string.zipcode_address) + " " + selectedZipcode.getAddress());
    		tvZipcode.setText(this.getString(R.string.zipcode_zipcode) + " " + selectedZipcode.getZipcode());

    		break;
    	}
    }

}

코드는 조잡하지만..
searchButton 을 클릭하면 Thread 로 getZipcodes 를 호출하게 되고, progressDialog 를 표시하게 된다.
getZipcodes 가 XML 데이터를 읽고 ListView 로 처리하는 과정을 마치게 되면,
Handler의 MessageQueue 에 updateResults 를 실행하라고 집어넣게 된다.
그러면 updateResults 가 실행이 되고, ListView 로 표시하는 작업이 끝나고, progressDialog 를 dismiss() 하고,
removeDialog()로 제거를 시킨다.

removeDialog() 로 제거를 해주지 않으면,
progressDialog 가 멈춘상태로 표시가 된다.

버그가 있을수도 있고..
코드가 우아하지 않지만.. 이런 삽질을 반복하지 않기 위해 기록해 두련다.ㅋㅋ

이상한 점이나, 개선점이 있으면 코멘트 남겨 주시길..

참고: Creating a ProgressDialog, [TinyTut] - Displaying a simple ProgressDialog (anddev.org)

Posted in android, development | Tagged , , , | Leave a comment