카테고리 보관물: 안드로이드

안드로이드에는 Crop Intent가 없습니다.

com.android.camera.action.CROP사용하지 마세요.

No, Android Does *Not* Have a Crop Intent

일반적으로 사진을 간단히 편집해서 불러오려고 할 경우에 com.android.camera.action.CROP을 action으로 한 Intent로 startActivity()를 호출해서 처리하는 경우가 많습니다. 저도 그렇게 사용하고 있었고요.
AOSP 카메라앱에서 이 Intent를 처리할 수 있고 많은 기기들에서 이렇게 사용하는 것이 가능한게 사실이지만 동작하지 않는 기기들도 존재합니다. 그리고 그런 기기들에서는 앱이 Crash됩니다.
저 같은 경우에는 일본의 docomo arrows F-04E, F-05D 같은 기기들에서 동작하지 않는다는 리포트가 많았습니다. 저는 PackageManager로 Crop Intent를 처리할 수 있는 앱이 있는지 먼저 체크하고 있었음에도 처리가 되지 않고 있다고해서 조금 놀랐었네요.

그래서 저 글에서도 제안하고 있고 제가 처리한 방법도 오픈소스를 이용하는 방법이었습니다.
몇몇 github 라이브러리들이 존재하는데 AOSP 카메라앱에서 소스를 따온 것 들입니다.

https://github.com/lvillani/android-cropimage – 쓰기 좋게 example도 제공하고 develop 브랜치에서 빌드가 가능합니다.
https://github.com/MMP-forTour/cropimage

ADT 22 DDMS에서 Heap tab 안 뜨는 문제

Android SDK Tools 22 DDMS에서 Heap이나 Network 탭이 안뜨는 문제가 있다.

http://code.google.com/p/android/issues/detail?id=55454
http://code.google.com/p/android/issues/detail?id=55517
http://code.google.com/p/android/issues/detail?id=55394

안 그래도 메모리 디버깅 중인데ㅠㅠ

22.1에서 수정될 것이라고 하며 Standalone DDMS.bat를 사용하거나 21.1의 tools/lib/monitor* 디렉토리를 덮어씌우는 방법으로 해결 가능

21.1 SDK는 http://code.google.com/p/android/issues/detail?id=55394에서 플랫폼별로 받을 수 있다.

https://dl.google.com/android/android-sdk_r21.1-windows.zip
https://dl.google.com/android/android-sdk_r21.1-macosx.zip
https://dl.google.com/android/android-sdk_r21.1-linux.tgz

Java에서 Javascript의 encodeURIComponent 구현하기

자바에서는 URLEncoder를 사용해서 인코딩을 할 수 있는데 자바스크립트에서 사용하는 encodeURIComponent와 살짝 다르다.

Java의 URLEncoder:

  • literal characters (regex representation): [-a-zA-Z0-9._*]
  • the space character " " is converted into a plus sign "+".

JavaScript의 encodeURIComponent():

  • literal characters (regex representation): [-a-zA-Z0-9._*~'()!]

즉, 자바에서는 빈칸을 ‘+‘로 바꾸고 자바스크립트는 빈칸을 ‘%20‘으로 변환,
그리고 자바스크립트에서는 ~'()!을 그대로 두지만 자바에서는 각각 UTF-8 인코딩시킨다.

결국 빈칸과 ~'()!을 변환시키면 URLEncoder의 결과를 encodeURIComponent의 결과와 동일하게 만들 수 있다.

 

public static String encodeURIComponent(String s)
  {
    String result = null;
 
    try
    {
      result = URLEncoder.encode(s, "UTF-8")
                         .replaceAll("\\+", "%20")
                         .replaceAll("\\%21", "!")
                         .replaceAll("\\%27", "'")
                         .replaceAll("\\%28", "(")
                         .replaceAll("\\%29", ")")
                         .replaceAll("\\%7E", "~");
    }
 
    // This exception should never occur.
    catch (UnsupportedEncodingException e)
    {
      result = s;
    }
 
    return result;
  }

안드로이드에서 개발한 앱과 서버간의 통신이 제대로 안되어 헤맸었는데 빈칸이 다르게 변환되는 것이 문제였다.

Java equivalent to JavaScript’s encodeURIComponent that produces identical output?

안드로이드 장치에서 이메일 주소 읽어오기

안드로이드 앱에서 사용자의 이메일 주소를 읽어오는 방법입니다.

회원가입시에 미리 입력 시켜둬서 사용자 편의성을 높이는데 사용할 수 있으며 악용하진 말아야할 것 입니다.

 

1. AccountManager 사용하기 (API 5 이상)

AccountManager를 이용하면  기기에 등록된 모든 계정이름을 불러올 수 있고 계정이름이 이메일인 경우가 많기 때문에 활용할 수 있습니다.

Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
    if (emailPattern.matcher(account.name).matches()) {
        String possibleEmail = account.name;
        ...
    }
}

AccountManager를 사용하려면 GET_ACCOUNTS 권한이 필요하니 AndroidManifest.xml에 권한을 추가해둬야 합니다.

<uses-permission android:name="android.permission.GET_ACCOUNTS" />

 

2. ContactsContract.Profile 이용하기 (API 14 이상)

ICS부터는 사용자의 프로필에 접근하여 이메일을 가져올 수 있습니다.

public class ExampleActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getLoaderManager().initLoader(0, null, this);
    }
 
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle arguments) {
        return new CursorLoader(this,
                // Retrieve data rows for the device user's 'profile' contact.
                Uri.withAppendedPath(
                        ContactsContract.Profile.CONTENT_URI,
                        ContactsContract.Contacts.Data.CONTENT_DIRECTORY),
                ProfileQuery.PROJECTION,
 
                // Select only email addresses.
                ContactsContract.Contacts.Data.MIMETYPE + " = ?",
                new String[]{ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE},
 
                // Show primary email addresses first. Note that there won't be
                // a primary email address if the user hasn't specified one.
                ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
    }
 
    @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        List<String> emails = new ArrayList<String>();
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            emails.add(cursor.getString(ProfileQuery.ADDRESS));
            // Potentially filter on ProfileQuery.IS_PRIMARY
            cursor.moveToNext();
        }
 
        ...
    }
 
    @Override
    public void onLoaderReset(Loader<Cursor> cursorLoader) {
    }
 
    private interface ProfileQuery {
        String[] PROJECTION = {
                ContactsContract.CommonDataKinds.Email.ADDRESS,
                ContactsContract.CommonDataKinds.Email.IS_PRIMARY,
        };
 
        int ADDRESS = 0;
        int IS_PRIMARY = 1;
    }
}

READ_PROFILEREAD_CONTACTS의 두 가지 권한이 필요합니다.

<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />

참조 : How to get the Android device’s primary e-mail address