Android/App개발2010. 4. 22. 15:05
Android 2.0에서부터 SyncAdapter를 통해 Contact정보를 다른 소스로부터 동기화를 지원한다.
Example을 하나 제공하는데 이 샘플의 테스트 방법이 developer.android.com에 정확하게 설명이 되어 있지 않다.

아래는 구글담당자의 테스트방법에 대한 메일내용이다.

Hi, 

I have uploaded the zipped source files for this sample at: 
http://code.google.com/p/apps-for-android/downloads/list 

Sorry about the server related python source files not being visible 
on developer.android.com. We will fix it soon. 
This sample source will be available with the next sdk package, we are 
working on making zipped samples downloadable from 
developer.android.com itself in future. 

Regarding password issue, please use account user1/test on 
samplesyncadapter server. 

I would recommend that to add new accounts, download the server code, 
modify it as you want and host it on a separate app engine instance. 
If you look at dashboard.py and app.yaml in server code it should be 
pretty clear how to do this..giving a short overview below: 
1) Add a new Sample SyncAdapter account @: 
http://samplesyncadapter.appspot.com/add_user 
For example I have added user1: 
http://samplesyncadapter.appspot.com/edit_user?user=1 
2) Enter username/password @ 
http://samplesyncadapter.appspot.com/add_credentials 
The password for user1 is test. 
3) Modify the android code to use your server instance. 

Sorry for the confusion so far, please let me know if you have more 
questions. 

Thanks, 
Megha 

On Feb 18, 10:28 am, HCH <hayeshau...@gmail.com> wrote: 


위와 같이 수행하여 계정을 추가한 후 추가한 계정의 Friends를 등록하면 Sync시 추가한 Friends가 Contacts에 동기되어 표시되는것을 확인할 수 있다. 이 때 Friends를 추가할 때 다른 계정의 Handle명을 입력해야 함을 주의해야 한다.


Posted by 삼스
Android/App개발2010. 4. 19. 16:39
볼륨키로 조절시 어떤때는 ringer볼륨, 어떤때는 music볼륨등 다르게 조절되는것을 볼수있다.
이 때 이값은 어떻게 결정될까?

AudioService의 getActiveStreamType(int suggestedStreamType)함수에 의해 요구한 볼륨조절값을 참조하여 현재 시스템의 상태에 따른 볼륨조절 믹서 종류를 구분하여 준다.

    private int getActiveStreamType(int suggestedStreamType) {
        boolean isOffhook = false;
        try {
            ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
            if (phone != null) isOffhook = phone.isOffhook();
        } catch (RemoteException e) {
            Log.w(TAG, "Couldn't connect to phone service", e);
        }

        if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) == AudioSystem.FORCE_BT_SCO) {
            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
            return AudioSystem.STREAM_BLUETOOTH_SCO;
        } else if (isOffhook) {
            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
            return AudioSystem.STREAM_VOICE_CALL;
        } else if (AudioSystem.isMusicActive()) {
            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC...");
            return AudioSystem.STREAM_MUSIC;
        } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
            // Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING...");
            return AudioSystem.STREAM_RING;
        } else {
            // Log.v(TAG, "getActiveStreamType: Returning suggested type " + suggestedStreamType);
            return suggestedStreamType;
        }
    }

함수의 구현내용을 살펴보면...
BT사용중이면 BT볼륨  -> Call중이면 VoiceCall볼륨 -> 음악재생중이면 Music 볼륨 -> 디폴트는 Ringer볼륨 의 순서로 결정된다.




Posted by 삼스
Android/App개발2010. 4. 19. 11:51
emulator에서는 phone과 notificatin ringtone이 하나도 뜨지 않아서 테스트를 할수가 없다.
이 때 Sdcard와 db파일을 일부조정하면 테스트가 가능하다.

1. emulator실행
2. DDMS에서 file explorer에서 scard폴더에 추가하고자 하는 ringtone파일들(여기서는 ogg파일들을 사용함)을 집어넣는다.
3. /data/data/com.android.providers.media/databases/external-xxxx.db파일을 꺼내온다.
4. 꺼낸 external-xxxx.db파일을 sqlitespy프로그램으로 아래 그림과 같이 audio_meta테이블에서 is_ringtone과 is_notification값을 1로 변경한다. is_alarm을 1로 하면 알람톤으로도 사용이 가능할것이다.
5. 변경한 external-xxxx.db파일을 emulator에 다시 집어 넣는다.
6. emulator를 다시 시작한다.


위의 순서로 하면 아래와 같이 링톤이 뜨게 된다.




Posted by 삼스
Android/App개발2010. 4. 13. 10:44

Command Line Shell For SQLite

The SQLite library includes a simple command-line utility named sqlite3 (or sqlite3.exe on windows) that allows the user to manually enter and execute SQL commands against an SQLite database. This document provides a brief introduction on how to use the sqlite3 program.

Getting Started

To start the sqlite3 program, just type "sqlite3" followed by the name the file that holds the SQLite database. If the file does not exist, a new one is created automatically. The sqlite3 program will then prompt you to enter SQL. Type in SQL statements (terminated by a semicolon), press "Enter" and the SQL will be executed.

For example, to create a new SQLite database named "ex1" with a single table named "tbl1", you might do this:

$ sqlite3 ex1
SQLite version 3.6.11
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table tbl1(one varchar(10), two smallint);
sqlite> insert into tbl1 values('hello!',10);
sqlite> insert into tbl1 values('goodbye', 20);
sqlite> select * from tbl1;
hello!|10
goodbye|20
sqlite>

You can terminate the sqlite3 program by typing your systems End-Of-File character (usually a Control-D). Use the interrupt character (usually a Control-C) to stop a long-running SQL statement.

Make sure you type a semicolon at the end of each SQL command! The sqlite3 program looks for a semicolon to know when your SQL command is complete. If you omit the semicolon, sqlite3 will give you a continuation prompt and wait for you to enter more text to be added to the current SQL command. This feature allows you to enter SQL commands that span multiple lines. For example:

sqlite> CREATE TABLE tbl2 (
   ...>   f1 varchar(30) primary key,
   ...>   f2 text,
   ...>   f3 real
   ...> );
sqlite>

Aside: Querying the SQLITE_MASTER table

The database schema in an SQLite database is stored in a special table named "sqlite_master". You can execute "SELECT" statements against the special sqlite_master table just like any other table in an SQLite database. For example:

$ sqlite3 ex1
SQLite vresion 3.6.11
Enter ".help" for instructions
sqlite> select * from sqlite_master;
    type = table
    name = tbl1
tbl_name = tbl1
rootpage = 3
     sql = create table tbl1(one varchar(10), two smallint)
sqlite>

But you cannot execute DROP TABLE, UPDATE, INSERT or DELETE against the sqlite_master table. The sqlite_master table is updated automatically as you create or drop tables and indices from the database. You can not make manual changes to the sqlite_master table.

The schema for TEMPORARY tables is not stored in the "sqlite_master" table since TEMPORARY tables are not visible to applications other than the application that created the table. The schema for TEMPORARY tables is stored in another special table named "sqlite_temp_master". The "sqlite_temp_master" table is temporary itself.

Special commands to sqlite3

Most of the time, sqlite3 just reads lines of input and passes them on to the SQLite library for execution. But if an input line begins with a dot ("."), then that line is intercepted and interpreted by the sqlite3 program itself. These "dot commands" are typically used to change the output format of queries, or to execute certain prepackaged query statements.

For a listing of the available dot commands, you can enter ".help" at any time. For example:

sqlite> .help
.backup ?DB? FILE      Backup DB (default "main") to FILE
.bail ON|OFF           Stop after hitting an error.  Default OFF
.databases             List names and files of attached databases
.dump ?TABLE? ...      Dump the database in an SQL text format
.echo ON|OFF           Turn command echo on or off
.exit                  Exit this program
.explain ON|OFF        Turn output mode suitable for EXPLAIN on or off.
.genfkey ?OPTIONS?     Options are:
                         --no-drop: Do not drop old fkey triggers.
                         --ignore-errors: Ignore tables with fkey errors
                         --exec: Execute generated SQL immediately
                       See file tool/genfkey.README in the source 
                       distribution for further information.
.header(s) ON|OFF      Turn display of headers on or off
.help                  Show this message
.import FILE TABLE     Import data from FILE into TABLE
.indices TABLE         Show names of all indices on TABLE
.iotrace FILE          Enable I/O diagnostic logging to FILE
.load FILE ?ENTRY?     Load an extension library
.mode MODE ?TABLE?     Set output mode where MODE is one of:
                         csv      Comma-separated values
                         column   Left-aligned columns.  (See .width)
                         html     HTML <table> code
                         insert   SQL insert statements for TABLE
                         line     One value per line
                         list     Values delimited by .separator string
                         tabs     Tab-separated values
                         tcl      TCL list elements
.nullvalue STRING      Print STRING in place of NULL values
.output FILENAME       Send output to FILENAME
.output stdout         Send output to the screen
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.restore ?DB? FILE     Restore content of DB (default "main") from FILE
.schema ?TABLE?        Show the CREATE statements
.separator STRING      Change separator used by output mode and .import
.show                  Show the current values for various settings
.tables ?PATTERN?      List names of tables matching a LIKE pattern
.timeout MS            Try opening locked tables for MS milliseconds
.timer ON|OFF          Turn the CPU timer measurement on or off
.width NUM NUM ...     Set column widths for "column" mode
sqlite>

Changing Output Formats

The sqlite3 program is able to show the results of a query in eight different formats: "csv", "column", "html", "insert", "line", "list", "tabs", and "tcl". You can use the ".mode" dot command to switch between these output formats.

The default output mode is "list". In list mode, each record of a query result is written on one line of output and each column within that record is separated by a specific separator string. The default separator is a pipe symbol ("|"). List mode is especially useful when you are going to send the output of a query to another program (such as AWK) for additional processing.

sqlite> .mode list
sqlite> select * from tbl1;
hello|10
goodbye|20
sqlite>

You can use the ".separator" dot command to change the separator for list mode. For example, to change the separator to a comma and a space, you could do this:

sqlite> .separator ", "
sqlite> select * from tbl1;
hello, 10
goodbye, 20
sqlite>

In "line" mode, each column in a row of the database is shown on a line by itself. Each line consists of the column name, an equal sign and the column data. Successive records are separated by a blank line. Here is an example of line mode output:

sqlite> .mode line
sqlite> select * from tbl1;
one = hello
two = 10

one = goodbye
two = 20
sqlite>

In column mode, each record is shown on a separate line with the data aligned in columns. For example:

sqlite> .mode column
sqlite> select * from tbl1;
one         two       
----------  ----------
hello       10        
goodbye     20        
sqlite>

By default, each column is at least 10 characters wide. Data that is too wide to fit in a column is truncated. You can adjust the column widths using the ".width" command. Like this:

sqlite> .width 12 6
sqlite> select * from tbl1;
one           two   
------------  ------
hello         10    
goodbye       20    
sqlite>

The ".width" command in the example above sets the width of the first column to 12 and the width of the second column to 6. All other column widths were unaltered. You can gives as many arguments to ".width" as necessary to specify the widths of as many columns as are in your query results.

If you specify a column a width of 0, then the column width is automatically adjusted to be the maximum of three numbers: 10, the width of the header, and the width of the first row of data. This makes the column width self-adjusting. The default width setting for every column is this auto-adjusting 0 value.

The column labels that appear on the first two lines of output can be turned on and off using the ".header" dot command. In the examples above, the column labels are on. To turn them off you could do this:

sqlite> .header off
sqlite> select * from tbl1;
hello         10    
goodbye       20    
sqlite>

Another useful output mode is "insert". In insert mode, the output is formatted to look like SQL INSERT statements. You can use insert mode to generate text that can later be used to input data into a different database.

When specifying insert mode, you have to give an extra argument which is the name of the table to be inserted into. For example:

sqlite> .mode insert new_table
sqlite> select * from tbl1;
INSERT INTO 'new_table' VALUES('hello',10);
INSERT INTO 'new_table' VALUES('goodbye',20);
sqlite>

The last output mode is "html". In this mode, sqlite3 writes the results of the query as an XHTML table. The beginning <TABLE> and the ending </TABLE> are not written, but all of the intervening <TR>s, <TH>s, and <TD>s are. The html output mode is envisioned as being useful for CGI.

Writing results to a file

By default, sqlite3 sends query results to standard output. You can change this using the ".output" command. Just put the name of an output file as an argument to the .output command and all subsequent query results will be written to that file. Use ".output stdout" to begin writing to standard output again. For example:

sqlite> .mode list
sqlite> .separator |
sqlite> .output test_file_1.txt
sqlite> select * from tbl1;
sqlite> .exit
$ cat test_file_1.txt
hello|10
goodbye|20
$

Querying the database schema

The sqlite3 program provides several convenience commands that are useful for looking at the schema of the database. There is nothing that these commands do that cannot be done by some other means. These commands are provided purely as a shortcut.

For example, to see a list of the tables in the database, you can enter ".tables".

sqlite> .tables
tbl1
tbl2
sqlite>

The ".tables" command is similar to setting list mode then executing the following query:

SELECT name FROM sqlite_master 
WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'
UNION ALL 
SELECT name FROM sqlite_temp_master 
WHERE type IN ('table','view') 
ORDER BY 1

In fact, if you look at the source code to the sqlite3 program (found in the source tree in the file src/shell.c) you'll find exactly the above query.

The ".indices" command works in a similar way to list all of the indices for a particular table. The ".indices" command takes a single argument which is the name of the table for which the indices are desired. Last, but not least, is the ".schema" command. With no arguments, the ".schema" command shows the original CREATE TABLE and CREATE INDEX statements that were used to build the current database. If you give the name of a table to ".schema", it shows the original CREATE statement used to make that table and all if its indices. We have:

sqlite> .schema
create table tbl1(one varchar(10), two smallint)
CREATE TABLE tbl2 (
  f1 varchar(30) primary key,
  f2 text,
  f3 real
)
sqlite> .schema tbl2
CREATE TABLE tbl2 (
  f1 varchar(30) primary key,
  f2 text,
  f3 real
)
sqlite>

The ".schema" command accomplishes the same thing as setting list mode, then entering the following query:

SELECT sql FROM 
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE type!='meta'
ORDER BY tbl_name, type DESC, name

Or, if you give an argument to ".schema" because you only want the schema for a single table, the query looks like this:

SELECT sql FROM
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'
ORDER BY substr(type,2,1), name

You can supply an argument to the .schema command. If you do, the query looks like this:

SELECT sql FROM
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE tbl_name LIKE '%s'
  AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'
ORDER BY substr(type,2,1), name

The "%s" in the query is replace by your argument. This allows you to view the schema for some subset of the database.

sqlite> .schema %abc%

Along these same lines, the ".table" command also accepts a pattern as its first argument. If you give an argument to the .table command, a "%" is both appended and prepended and a LIKE clause is added to the query. This allows you to list only those tables that match a particular pattern.

The ".databases" command shows a list of all databases open in the current connection. There will always be at least 2. The first one is "main", the original database opened. The second is "temp", the database used for temporary tables. There may be additional databases listed for databases attached using the ATTACH statement. The first output column is the name the database is attached with, and the second column is the filename of the external file.

sqlite> .databases

Converting An Entire Database To An ASCII Text File

Use the ".dump" command to convert the entire contents of a database into a single ASCII text file. This file can be converted back into a database by piping it back into sqlite3.

A good way to make an archival copy of a database is this:

$ echo '.dump' | sqlite3 ex1 | gzip -c >ex1.dump.gz

This generates a file named ex1.dump.gz that contains everything you need to reconstruct the database at a later time, or on another machine. To reconstruct the database, just type:

$ zcat ex1.dump.gz | sqlite3 ex2

The text format is pure SQL so you can also use the .dump command to export an SQLite database into other popular SQL database engines. Like this:

$ createdb ex2
$ sqlite3 ex1 .dump | psql ex2

Other Dot Commands

The ".explain" dot command can be used to set the output mode to "column" and to set the column widths to values that are reasonable for looking at the output of an EXPLAIN command. The EXPLAIN command is an SQLite-specific SQL extension that is useful for debugging. If any regular SQL is prefaced by EXPLAIN, then the SQL command is parsed and analyzed but is not executed. Instead, the sequence of virtual machine instructions that would have been used to execute the SQL command are returned like a query result. For example:

sqlite> .explain
sqlite> explain delete from tbl1 where two<20;
addr  opcode        p1     p2     p3          
----  ------------  -----  -----  -------------------------------------   
0     ListOpen      0      0                  
1     Open          0      1      tbl1        
2     Next          0      9                  
3     Field         0      1                  
4     Integer       20     0                  
5     Ge            0      2                  
6     Key           0      0                  
7     ListWrite     0      0                  
8     Goto          0      2                  
9     Noop          0      0                  
10    ListRewind    0      0                  
11    ListRead      0      14                 
12    Delete        0      0                  
13    Goto          0      11                 
14    ListClose     0      0

The ".timeout" command sets the amount of time that the sqlite3 program will wait for locks to clear on files it is trying to access before returning an error. The default value of the timeout is zero so that an error is returned immediately if any needed database table or index is locked.

And finally, we mention the ".exit" command which causes the sqlite3 program to exit.

Using sqlite3 in a shell script

One way to use sqlite3 in a shell script is to use "echo" or "cat" to generate a sequence of commands in a file, then invoke sqlite3 while redirecting input from the generated command file. This works fine and is appropriate in many circumstances. But as an added convenience, sqlite3 allows a single SQL command to be entered on the command line as a second argument after the database name. When the sqlite3 program is launched with two arguments, the second argument is passed to the SQLite library for processing, the query results are printed on standard output in list mode, and the program exits. This mechanism is designed to make sqlite3 easy to use in conjunction with programs like "awk". For example:

$ sqlite3 ex1 'select * from tbl1' |
>  awk '{printf "<tr><td>%s<td>%s\n",$1,$2 }'
<tr><td>hello<td>10
<tr><td>goodbye<td>20
$

Ending shell commands

SQLite commands are normally terminated by a semicolon. In the shell you can also use the word "GO" (case-insensitive) or a slash character "/" on a line by itself to end a command. These are used by SQL Server and Oracle, respectively. These won't work insqlite3_exec(), because the shell translates these into a semicolon before passing them to that function.

Compiling the sqlite3 program from sources

The source code to the sqlite3 command line interface is in a single file named "shell.c" which you can download from the SQLite website. Compile this file (together with the sqlite3 library source code to generate the executable. For example:

gcc -o sqlite3 shell.c sqlite3.c -ldl -lpthread

Posted by 삼스
Android/App개발2010. 3. 18. 12:07
http://android-developers.blogspot.com/2010/02/live-wallpapers.html

Live wallpapers

Android 2.1에서 소개된 libe wallpaper로 사용자는 이제 더 풍부하고, 애니매이션가능하고 더 인터랙티브한 그들만의 홈스크린을 즐길수 있게 되었다. live wallpaper는 일반 Android application과 아주 유사하고 플랫폼의 모든 자산에 접근이 가능하다: SGL(2D drawing), OpenGL(3D drawing), GPS, accelerometers, network access, .... Nexus One에 들어가 있는 live wallpaper는 이런 API들을 이용하여 더 재미있고 흥미있는 UX의 예를 보여준다. 예를 들어 Grass wallpaper는 폰의 위치를 가지고 해가뜰때와 질때는 구분하여 하늘 이미지를 적절히 표시한다.


자신만의 live wallpaper를 만드는것은 쉽고, SurfaceView와 Canvas를 다루어보았다면 특히 더 쉽다. 작성방법을 배우려면 Android 2.1SDK에서 제공하는 CubeLiveWallpaper예제를 받아야 한다(android-2.1/samples/CubeLiveWallpaper에 있다)

Live wallpaper는 일반적인 Android service와 유사하다. 한가지 다른점은 onCreateEngine()이라는 메서드가 추가된것이다. 이 메서드는 WallpaperService.Engine을 생성하기 위해서 있다. 이 엔진은 wallpaper의 lifecycle을 관리하고 그리는것에 대한 처리를 담당한다. 시스템은 그릴수 있는 surface를 제공한다. wallpaper그리기는 아주 비용이 비싸기 때문에 가능한 CPU자원을 많이 사용하지 않도록 피해서 코드를 최적화해야 한다. 이는 wallpaper의 lifecycle관리가 중요한 이유이기도 한다. wallpaper가 화면에서 보여지지 않을때 wallpaper는 관련된 모든 activity를 stop해야 한다.

엔진은 또한 사용자나 Home app와 상호작용하기 위해 몇가지 메서드를 구현할 수 있다. 사용자가 다른 home screen으로 이동하기 위해 scroll하기를 원한다면 onOffsetChanged()를 사용할 수 있다. touch event를 처리하고자 한다면 onTouchEvent(MotionEvent)를 구현할 수 있다. 마지막으로 app들이 live wallpaper에 명령을 보낼수 있다. 현재는 표준 home app만이 live wallpaper의 onCommand()로 명령을 보낼수 있다 :

  • android.wallpaper.tap : 사용자가 워크스페이스상의 비어있는 곳을 tap할 때 사용됨. Water live wallpaper에서 사용자가 터치한 부분에서 새로운 물줄기가 생성되도록 구현할때 사용되었다.
  • android.home.drop : 사용자가 워크스페이스상에 ICON이나 Widget을 drop할때 사용됨.

Live wallpaper는 Android 2.1의 기능이다. 당신이 만든 live wallpaper를 다운로드하여 잘 동작할것을 보장하기 위해서는 manifest에 아래와 같이 기술해야 한다는 것을 기억하라 :

  • <uses-sdk android:minSdkVersion="7" />, Android 2.1에서 동작하도록 설정.
  • <uses-feature android:name="android.software.live_wallpaper" />, live wallpaper임을 설정

많은 live wallpaper들이 미리 마켓에 많으니 사용해보삼.

Posted by 삼스
Android/App개발2010. 3. 17. 16:23
http://android-developers.blogspot.com/2010/03/speech-input-api-for-android.html

사람들은 그들이 어디에 있건 만질 수 있다는것 때문에 모바일폰을 선호한다. 그것은 단지 통화뿐이 아니라 이메일, 문자, 마이크로블로깅 등등을 이용할 수 있다는 것을 의미한다. 여기에 search by voice와 voice shortcuts이 추가되었다. Android 2.1에 voice-enabled keyboard로 추가하였으며 이는 연결을 유지하는것도 쉽게 해준다. 이제 당신은 메세지를 타이핑하지 않고 작성가능하다. 그냥 keyboard상의 마이크모양 버튼을 누르기만 하면 된다.

우리는 speech기능이 모바일경험의 근본적인 변화를 일으킬수 있다고 믿는다. 우리는 모든 안드로이드 개발자들을 Android SDK을 이용하여 음성입력기능을 통합하는데 관심을 갖도록 초대하고 싶다. 내가 즐겨 사용하는 음성인식기능어플중에 Handcent SMS을 사용하는데 SMS에 대한 답장을 SMS popup window을 tab함으로써 쉽게 할 수 있다.

Speech input integrated into Handcent SMS

Android SDK는 어플개발시 쉽게 바로 사용할수 있도록 해준다. 그냥 sample application 의 코드를 copy-paste하면 된다. 안드로이드는 오픈플랫폼이기 때문에 당신의 어플은 RecognizerIntent을 수신하는 receiver를 등록하여 임의 어떤 음성인식 어플이든지 만들수 있다. 많은 안드로이드 디바이스에 기본적으로 탑재되어 있는 구글의 Voice Search App는 "Speak now" 팝업을 통해 RecognizerIntent에 응답하며 Google의 서버에 오디오를 전송한다-search widget이나 voice-enabled keyboard상의 마이크 아이콘을 선택했을때에도 이 서버가 이용된다(Settings->Applications->Manage applications에서 Voice Search가 설치되어 있는지 확인가능하다)

중요한 한가지 팀: 음성인식을 가능한 정확하게 하려면, 대화에 어떤 단어가 사용되는지에 대해 아는것이 도움이 된다. email이나 SMS메세지 작성시에는 "Mom, I'm writing you this message with my voice!"같은 유형이 적당할것이며 Google Search에서는 "weather in Mountain View"같이 말하는것이 적당할 것이다. 당신은 사용자가 적절한 language model을 요구하는것으로 최고의 경험을 가능하도록 할 수 있다: "free_form"은 dictation, "web_search"는 더 짧은 검색같은 구문에 적당하다.  우리는 Nexus One의 voice keyboard에서 dictation의 정확도를 향상시키기 위해 "free_form"모델을 개발했다. 반면 "web search"모델은 사용자가 음성으로 검색하고자 할때 사용된다.

Google의 서버는 현재 영어, 만다린(중국), 일본어만 지원한다. Web search 모델은 3가지를 모두 지원하며 free-form모델은 영어에만 최적화되어 있다. 앞으로 더 다양한 언어와 정확도를 개선해 나갈것이며 이를 개발자들이 사용할 수 있게 될것이다.


Posted by 삼스
Android/App개발2010. 2. 23. 21:50

SDK로 App개발시에는 eclipse의 debug기능을 사용할수도 있으나 플랫폼 개발시에는 이런 방법이 안통한다.

이떄 아래 코드처럼 일부러 exception을 발생시킨다음. try catch문을 이용해서 call stack을 찍어주면 해당 함수가 호출될때마다 Logcat에 호출경로를 찍어줍니다.


    @Override
    public void setVolumeControlStream(int streamType) {

        Log.d(TAG, "setVolumeControlStream -> " + streamType);        

        mVolumeControlStreamType = streamType;
      try {
         int c=1; c = c/0;

     } catch(Exception e) {

         e.printStackTrace();    

     }    

    }


Posted by 삼스
Android/App개발2010. 2. 7. 15:50
Posted by 삼스
Android/App개발2010. 2. 7. 15:50

Controls for the Android OS
Keyboard OS function
Escape Back button
Home Home button
F2, PageUp Menu (Soft-Left) button
Shift-F2, PageDown Star (Soft-Right) button
F3 Call/Dial button
F4 Hangup/EndCall button
F5 Search button
F7 Power button
Ctrl-F3, Ctrl-KEYPAD_5 Camera button
Ctrl-F5, KEYPAD_PLUS Volume up button
Ctrl-F6, KEYPAD_MINUS Volume down button
KEYPAD_5 DPad center
KEYPAD_4 DPad left
KEYPAD_6 DPad right
KEYPAD_8 DPad up
KEYPAD_2 DPad down
Controls for the Android Emulator
Keyboard Emulator function
F8 toggle cell network on/off
F9 toggle code profiling (when -trace option set)
Alt-ENTER toggle fullscreen mode
Ctrl-T toggle trackball mode
Ctrl-F11, KEYPAD_7 switch to previous layout
Ctrl-F12, KEYPAD_9 switch to next layout
KEYPAD_MULTIPLY increase onion alpha
KEYPAD_DIVIDE decrease onion alpha
Posted by 삼스
Android/App개발2009. 11. 6. 16:21

[Intro]

 

Android에서 사용하는 이미지는 Bitmap이라는 클래스에서 다~ 알아서 해줍니다.
그리고 이런 Bitmap Object를 쉽게 만들 수 있도록 도와주는 
BitmapFactory 클래스 라는 것도 있습니다.

 

BitmapFactory는 여러가지 소스로 부터 Bitmap Object를 만들어 주는 일을 하는데,
전부 static이며 decodeXXX 라는 이름을 가진 메소드들로 이루어져 있습니다.

XXX에는 어떤 것으로 부터 decode를 하여 
Bitmap Object를 만들어 낼지에 대한 말들이 들어 가겠죠.

 


[Decoding Methods]

 

BitmapFactory.decodeByteArray() 메소드는 Camera.PictureCallback 으로 부터 받은
Jpeg 사진 데이터를 가지고 Bitmap으로 만들어 줄 때 많이 사용 합니다.
Camera.PictureCallback에서 들어오는 데이터가 byte[] 형식이기 때문에
저 메소드를 사용 해야 하는 것이죠.

 

BitmapFactory.decodeFile() 메소드는 파일을 그대로 읽어 옵니다.
내부적으로는 파일 경로를 가지고 FileInputStream을 만들어서 decodeStream을 합니다.
그냥 파일 경로만 쓰면 다 해주는게 편리 한 것이죠.

 

BitmapFactory.decodeResource() 메소드는 Resource로 부터 Bitmap을 만들어 내며
BitmapFactory.decodeStream() 메소드는 InputStream으로 부터 Bitmap을 만들어 냅니다.
뭐 그냥 이름만 봐도 알 수 있는 것들이지요.

 


[OutOfMemoryError??]

 

보통 이미지 파일을 읽어서 Resizing을 해야 할 때가 있는데, 
그럴때는 BitmapFactory로 읽어서 Bitmap.createScaledBitmap() 메소드를 사용하여 줄이면

간단하게 처리 할 수 있습니다.

 

그런데 BitmapFactory를 사용할 때 주의해야 할 점이 있습니다.
아래의 예를 한번 보시죠.

Bitmap src = BitmapFactory.decodeFile("/sdcard/image.jpg");
Bitmap resized = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true);

이미지 파일로부터 Bitmap을 만든 다음에

다시 dstWidth, dstHeight 만큼 줄여서 resized 라는 Bitmap을 만들어 냈습니다.
보통이라면 저렇게 하는게 맞습니다.

 

읽어서, 줄인다.

 

그런데 만약 이미지 파일의 크기가 아주 크다면 어떻게 될까요?
지금 Dev Phone에서 카메라로 촬영하면
기본적으로 2048 x 1536 크기의 Jpeg 이미지가 촬영된 데이터로 넘어옵니다.
이것을 decode 하려면 3MB 정도의 메모리가 필요 할 텐데,

과연 어떤 모바일 디바이스에서 얼마나 처리 할 수 있을까요?

 

실제로 촬영된 Jpeg 이미지를 여러번 decoding 하다보면

아래와 같은 황당한 메세지를 발견 할 수 있습니다.

java.lang.OutOfMemoryError: bitmap size exceeds VM budget

네... OutOfMemory 입니다.
더 이상 무슨 말이 필요 하겠습니까...
메모리가 딸려서 처리를 제대로 못합니다.

 

이것이 실제로 decoding 후 메모리 해제가 제대로 되지 않아서 그런 것인지, 
하더라도 어디서 Leak이 발생 하는지에 대한 정확한 원인은 알 수 없습니다.
이것은 엔지니어들이 해결해야 할 문제 겠죠...

 

하지만 메모리 에러를 피할 수 있는 방법이 있습니다.

 


[BitmapFactory.Options.inSampleSize]

 

BitmapFactory.decodeXXX 시리즈는 똑같은 메소드가 두 개씩 오버로딩 되어 있습니다.
같은 이름이지만 Signature가 다른 메소드의 차이점은
BitmapFactory.Options를 파라메터로 받느냐 안받느냐의 차이죠.

BitmapFactory.Options를 사용하게 되면 decode 할 때 여러가지 옵션을 줄 수 있습니다.


여러가지 많지만 저희가 지금 사용할 것은 inSampleSize 옵션 입니다.

 

inSampleSize 옵션은,
애초에 decode를 할 때 얼마만큼 줄여서 decoding을 할 지 정하는 옵션 입니다.

 

inSampleSize 옵션은 1보다 작은 값일때는 무조건 1로 세팅이 되며,
1보다 큰 값, N일때는 1/N 만큼 이미지를 줄여서 decoding 하게 됩니다.
즉 inSampleSize가 4라면 1/4 만큼 이미지를 줄여서 decoding 해서 Bitmap으로 만들게 되는 것이죠.

 

2의 지수만큼 비례할 때 가장 빠르다고 합니다.
2, 4, 8, 16... 정도 되겠죠?

 

그래서 만약 내가 줄이고자 하는 이미지가 1/4보다는 작고 1/8보다는 클 때,
inSampleSize 옵션에 4를 주어서 decoding 한 다음에,

Bitmap.createScaledBitmap() 메소드를 사용하여 한번 더 줄이면 됩니다.

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap src = BitmapFactory.decodeFile("/sdcard/image.jpg", options);
Bitmap resized = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, true);

당연한 이야기 이겠지만,
내가 원하고자 하는 사이즈가 딱 1/4 크기라면

Bitmap.createScaledBitmap() 메소드를 쓸 필요가 없지요.

 

inSampleSize 옵션을 잘 활용하면 메모리 부족 현상을 대략적으로 해소 할 수 있습니다.
참고로 제가 저 옵션을 사용한 뒤로는 메모리 에러를 본적이 한~번도 없답니다.

 


[Appendix]

 

inSampleSize 옵션을 사용하면

SkScaledBitmapSampler Object (Library Level) 를 생성 하게 되는데,
Object를 만들때 정해진 SampleSize 만큼 축소하여 width와 height를 정한 뒤에 만들게 됩니다.
그러니까 애초에 축소된 사이즈로 이미지를 decoding 하는 것이죠.

 


[Outro]

 

Android의 기본 어플리케이션 소스를 분석 하다보면
상당히 테크니컬한 기법들을 많이 얻을 수 있습니다.
어떻게 이런 방법으로 만들었나 싶을 정도로 매우 정교하고 복잡하게 만들어져 있지요.
참 대단한 것 같습니다.

 

아 그리고 왜 dstWidth와 dstHeight 변수 선언이 없냐고 따지시는 분들 설마 없겠죠?


Posted by 삼스