2013년 6월 18일 화요일

Android에서 java.util.Properties 사용하기

이전 블로그에서 이전 함 (원본 글 2013/06/18 작성)

Android에서 Properties를 사용할 필요가 있어 확인해 보니..


Asset Manager를 통해서 접근하는 방법과 res로 접근하는 방법이 있었음.
첫번째로 하긴 했는데.. 두번째는 안해봐서 ㅎㅎ

 Resources resources = this.getResources();
AssetManager assetManager = resources.getAssets();

// Read from the /assets directory
try {
    InputStream inputStream = assetManager.open("microlog.properties");
    Properties properties = new Properties();
    properties.load(inputStream);
    System.out.println("The properties are now loaded");
    System.out.println("properties: " + properties);
} catch (IOException e) {
    System.err.println("Failed to open microlog property file");
    e.printStackTrace();
}
The code is dead simple and thank God for the Properties class, although microproperties would do the trick. The second way to do it is as simple as the first approach. The code looks like this:
// Read from the /res/raw directory
try {
    InputStream rawResource = resources.openRawResource(R.raw.micrologv2);
    Properties properties = new Properties();
    properties.load(rawResource);
    System.out.println("The properties are now loaded");
    System.out.println("properties: " + properties);
} catch (NotFoundException e) {
    System.err.println("Did not find raw resource: "+e);
} catch (IOException e) {
    System.err.println("Failed to open microlog property file");
}

2013년 6월 17일 월요일

SQLite Parameterized statement, rawQuery()

이전 블로그에서 이전 함 (원본 글 2013/06/17 작성)

Android SQLite 사용 중 rawQuery의 arguments를 사용할 필요가 있을까 했는데..

public Cursor rawQuery (String sql, String[] selectionArgs)


찾다 보니 아래와 같은 의견이 있었음.


You should make use of the rawQuery method's selectionArgs parameter:
p_query = "select * from mytable where name_field = ?";
mDb.rawQuery(p_query, new String[] { uvalue });
This not only solves your quotes problem but also mitigates SQL Injection.
share|improve this answer
3 
I wish I could upmod this more than once! – jrockway Aug 18 '09 at 20:52
1 
It is also much faster because Sqlite doesn't have to parse every sql statement. – tuinstoel Aug 19 '09 at 20:33
12 
Indeed, you should use query arguments. However, you can also use the DatabaseUtils to escape strings, if needed. For instance, DatabaseUtils.sqlEscapeString(). It's not the best way, but it's available. Could be useful if you're trying to pass a raw SQL statement over to something external. – lilbyrdie Aug 22 '09 at 15:50
1 
@lilbyrdie: thanks! As one can't bind vectors of strings for use with the IN operator, sqlEscapeSting() was just what I needed! – Steve Pomeroy Jan 13 '11 at 22:33
This doesn't work as well as you'd think. If you use a string like this it breaks: "sample " string ' that breaks stuff" – Christopher Perry Aug 24 '12 at 3:20


Wikipedia에서 찾아보니.
SQL injection attack의 방지법으로 하나로 소개되어 있음..

SQLite Query Reserved Keywords

이전 블로그에서 이전 함 (원본 글 2013/06/17 작성)

DB creation이 안되서 계속 확인하고 있었는데..
reserved keyword인 group을 field name으로 사용하고 있었음.. 삽질했네..


Regardless of the compile-time configuration, any identifier that is not on the following 121 element list is not a keyword to the SQL parser in SQLite:
ABORT
ACTION
ADD
AFTER
ALL
ALTER
ANALYZE
AND
AS
ASC
ATTACH
AUTOINCREMENT
BEFORE
BEGIN
BETWEEN
BY
CASCADE
CASE
CAST
CHECK
COLLATE
COLUMN
COMMIT
CONFLICT
CONSTRAINT
CREATE
CROSS
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
DATABASE
DEFAULT
DEFERRABLE
DEFERRED
DELETE
DESC
DETACH
DISTINCT
DROP
EACH
ELSE
END
ESCAPE
EXCEPT
EXCLUSIVE
EXISTS
EXPLAIN
FAIL
FOR
FOREIGN
FROM
FULL
GLOB
GROUP
HAVING
IF
IGNORE
IMMEDIATE
IN
INDEX
INDEXED
INITIALLY
INNER
INSERT
INSTEAD
INTERSECT
INTO
IS
ISNULL
JOIN
KEY
LEFT
LIKE
LIMIT
MATCH
NATURAL
NO
NOT
NOTNULL
NULL
OF
OFFSET
ON
OR
ORDER
OUTER
PLAN
PRAGMA
PRIMARY
QUERY
RAISE
REFERENCES
REGEXP
REINDEX
RELEASE
RENAME
REPLACE
RESTRICT
RIGHT
ROLLBACK
ROW
SAVEPOINT
SELECT
SET
TABLE
TEMP
TEMPORARY
THEN
TO
TRANSACTION
TRIGGER
UNION
UNIQUE
UPDATE
USING
VACUUM
VALUES
VIEW
VIRTUAL
WHEN
WHERE

2013년 6월 14일 금요일

Memory Analyzer(memory leak detector), Android method profiling

이전 블로그에서 이전 함 (원본 글 2013/06/14 작성)

링크정리...

[Android상에서 Bitmap 처리 관련 링크들 및
 Out Of Memory에 대한 개인적인 방안]

[Eclipse Memory Analyzer (MAT)]
: memory leak 확인을 위해 사용하는 툴

[Related Links]

: Eclipse Memory Analyzer Tool (MAT) 사이트
  여러 자료가 링크 되어 있음.

: MAT 관련 설치, 간락한 사용법 소개

: 안드로이드 관점에서 GC와 memory leak 확인 및 처리 방법 관련 설명
: 위의 링크와 함께 봐야할 Google I/O 2011 세션 동영상 (Google I/O 2011: Memory management for Android Apps)

: 일반적인 메모리릭 예제 및 조언

: 메모리릭 확인 및 해결 실제 예제

[Installation]
 2. Installation
Install Eclipse MAT via the Eclipse Update manager Select General Purpose Tools and install theMemory Analyzer and Memory Analyzer (Charts) .

[How to use]

: 간략 버전

  1. Open DDMS perspective in Eclipse.
  2. Select Devices tab.
  3. Choose a process you want to make a dump for.
  4. Click Dump HPROF file button. The dump will be made and MAT window will be opened, assuming MAT is installed.
  5. Choose Leak Suspects Report in the wizard window and click Finish.

* 5번 단계가 끝나면 리포트가 나오게 되는데 리포트에서
  dominator_tree view를 선택한뒤 의심이 가는 항목을 선택하고 오른쪽 클릭 후 > Path To GC Roots > exclude weak references 를 선택하여 leak 원인 확인
 => 관련 내용은 위에 링크된 Google I/O 동영상에서 29-35분 사이를 참고.



1.3. Use the Eclipse Memory Analyzer

After a new heap dump with the .hprof ending has been created, you can open it via a double-click in Eclipse. You may need to refresh your project (F5 on the project). Double-click the file and select theLeak Suspects Report.


The overview page allows you to start the analysis of the heap dump. The dominator tree gives quickly an overview of the used objects.





[Profiling with Traceview and dmtracedump]

[메소드 프로파일링(profiling or tracing)]

2013년 6월 11일 화요일

Android SparseArray

이전 블로그에서 이전 함 (원본 글 2013/06/11 작성)

일반적으로 사용하는 자료구조 중 하나가
Map<Integer, String> 인데 data collision으로 인한 성능 문제로
Android에서는 SparseArray를 추천하고 있다.
하지만 Java Collection Interface를 지원하지는 않는데... 왜?!

[SparseArray]

 public classSparseArrayextends Objectimplements Cloneable
java.lang.Object
   ↳android.util.SparseArray<E>


[HashMap, SparseArray 사용]

별 차이는 없음.
 Old code with HashMap
 Map<Integer, Bitmap> _bitmapCache = new HashMap<Integer, Bitmap>();
   private void fillBitmapCache() {
        _bitmapCache.put(R.drawable.icon, BitmapFactory.decodeResource(getResources(), R.drawable.icon));
        _bitmapCache.put(R.drawable.abstrakt, BitmapFactory.decodeResource(getResources(), R.drawable.abstrakt));
        _bitmapCache.put(R.drawable.wallpaper, BitmapFactory.decodeResource(getResources(), R.drawable.wallpaper));
        _bitmapCache.put(R.drawable.scissors, BitmapFactory.decodeResource(getResources(), 
    }
 
Bitmap bm = _bitmapCache.get(R.drawable.icon);
New code with SparseArray
 SparseArray<Bitmap> _bitmapCache = new SparseArray<Bitmap>();
   private void fillBitmapCache() {
        _bitmapCache.put(R.drawable.icon, BitmapFactory.decodeResource(getResources(), R.drawable.icon));
        _bitmapCache.put(R.drawable.abstrakt, BitmapFactory.decodeResource(getResources(), R.drawable.abstrakt));
        _bitmapCache.put(R.drawable.wallpaper, BitmapFactory.decodeResource(getResources(), R.drawable.wallpaper));
        _bitmapCache.put(R.drawable.scissors, BitmapFactory.decodeResource(getResources(), 
    }
 
Bitmap bm = _bitmapCache.get(R.drawable.icon);



[SparseArray iteration]
Collection interface 미지원으로 이렇게 loop을 사용해야 한다.. 귀찮아..

up vote83down voteaccepted
seems I found the solution. I havent properly noticed keyAt(index) function.
So I'll go with something like this
int key = 0;
for(int i = 0; i < sparseArray.size(); i++) {
   key = sparseArray.keyAt(i);
   // get the object by the key.
   Object obj = sparseArray.get(key);
}
share|improve this answer


[Map, HashMap 그리고 SparseArray 설명]


[ParseArray Versus Hashmap 성능 비교]

 Results SparseArray Results
The SparseArray is a very quick data structure for sizes of 10,000 and less. If you are pulling data from your array considerably more than adding to it, you can get away with a size of 100,000. It starts to slow down a bit with the jump to 1,000, but nothing too surprising.
 Hashmap Results