着信音アプリ、簡単とはいえやはりいろいろありますね・・
先日、Android向け着信音集アプリをリリースしました。
簡単だよなあと思ったのですが、何点か結構かかってしまった点があるので、
メモ代わりに残します。
■後方互換(1.6と2.1への両対応)
基本的に、1.6向けのプログラムは2.1で動くのですが、
一点だけ、アドレス帳の1人1人に着信音を設定出来るのですが、
それが2.1では貼り付けることが出来ませんでした。
(音自体は、リストには入るのですが)
それで、2.1向けに書くと、
Cursor c = mAdapter.getCursor();
int dataIndex = c.getColumnIndexOrThrow(People._ID);
String contactId = c.getString(dataIndex);
Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, contactId);
ArrayList ops = new ArrayList();
ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(uri);
builder.withValue(ContactsContract.Contacts.CUSTOM_RINGTONE, newRingtoneUri.toString());
ops.add(builder.build());
try{
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
} catch(Exception e) { }
という様に変えることで動作するようになったものの、
2.1向けのapiを使っている部分があり、このままでは1.6では動かないことに。
こういう場合、
http://www.textdrop.net/soft/android-backword-compatibility/
にあるように、1.6設定で、2.1向けの部分のみ、
if(Integer.valueOf(Build.VERSION.SDK) >= 5)
で分離させ、reflectionを駆使して
以下のように書き換える必要がありました。
ArrayList ops = new ArrayList();
Class contentProviderOperation = Class.forName(“android.content.ContentProviderOperation”);
Method newUpdate = contentProviderOperation.getMethod(“newUpdate”, new Class[] { Uri.class } );
Class contentProviderOperation_Builder = Class.forName(“android.content.ContentProviderOperation$Builder”);
Method build = contentProviderOperation_Builder.getMethod(“build”, null );
Method withValue = contentProviderOperation_Builder.getMethod(“withValue”, new Class[] { String.class , Object.class } );
Class ContactsContract_Contacts = Class.forName(“android.provider.ContactsContract$Contacts”);
Uri CONTENT_URI = (Uri)ContactsContract_Contacts.getField(“CONTENT_URI”).get(ContactsContract_Contacts);
Uri uri = Uri.withAppendedPath(CONTENT_URI, contactId);
String customRingTone = (String)ContactsContract_Contacts.getField(“CUSTOM_RINGTONE”).get(ContactsContract_Contacts);
Object builderObject = ((Object) newUpdate.invoke(null, uri));
withValue.invoke(builderObject, customRingTone, newUri.toString());
ops.add(build.invoke(builderObject, null));
Class ContactsContract = Class.forName(“android.provider.ContactsContract”);
String AUTHORITY = (String)ContactsContract.getField(“AUTHORITY”).get(ContactsContract);
Method applyBatch = ContentResolver.class.getMethod(“applyBatch”, new Class[] { String.class , ArrayList.class});
applyBatch.invoke(mainContext.getContentResolver(), AUTHORITY, ops);
全くreflectionなど使ったこと無かったので、
java的に、書いていくのが大変でした。
■HT-03Aで・・
着信音を登録していくと、どんどん着信音リストに貯まって行ってしまうので、
端末にある着信音のリストを見て、もし既にあればそのUriから設定するようにしたところ、
HT-03Aでは「アプリが停止しています 強制終了しますか、待機しますか」
というような”待ち”ウインドウが出てしまいました。
(他の端末や、エミュレーションでは問題なし。)
ちなみにリストからのチェックは、以下のような関数を実行していて、
音は30個とか40個とかしかなくとも、もうその数だけでも”待ち”状態になってしまいました。
public static Uri ringtoneExsistUri(Context mainContext , String soundName , int RingToneType){
RingtoneManager rm = new RingtoneManager(mainContext);
rm.setType(RingToneType);
Cursor cursor = rm.getCursor();
if (cursor != null) {
int repeatCount = cursor.getCount();
for(int i = 0 ; i < repeatCount ; i++){
Ringtone ringtone = rm.getRingtone(i);
String currentTitle = ringtone.getTitle(mainContext);
if(currentTitle.equals(soundName)){
return rm.getRingtoneUri(i);
}
}
}
return null;
}
登録までには、
上記の既にあるかチェック→リソースから音ファイルに変換(ファイル化してどこかに置かないと着信音として設定出来ないので)→設定
という流れがあるのですが、それらを全てバックグラウンド動作に書き換えることで、
この現象は回避出来ました。
(バックグラウンド動作は、
http://wikiwiki.jp/android/?AsyncTask%A4%C7%A5%D0%A5%C3%A5%AF%A5%B0%A5%E9%A5%A6%A5%F3%A5%C9%BD%E8%CD%FD%A4%F2%B9%D4%A4%A6
を参考にさせていただきました。)
やはり「1本ちゃんと出す」と言うことは
結構いろいろありますが、すごく勉強になりました。
ちなみに、アプリは「着信音~日本の音」
http://www.zerohachi.jp/ringtone01/index_jp.html
という、そのままの名前で99円でマーケットで販売しております、
もしよければご購入いただければありがたいです。
※その他、参考にさせていただいたサイト
http://d.hatena.ne.jp/tomorrowkey/20090826/1251294895
http://code.google.com/p/ringdroid/
http://clipboard.blog.so-net.ne.jp/2010-05-01
