やりたいことはシンプルに、緊急電話やフリーダイヤル以外の発信時に必ず0063を頭につけるということです。
BroadcastReceiverでoutgoing callをキャッチし、プリフィックスを付加して新たなoutgoing callを発する動作をします。
下記の記事などを参考にしました。
How do you receive outgoing call in broadcastreceiver
mainActivity.java
PreferenceActivityで作ろうとしたのですが、Spinnerのように現状で選択している項目を表示させることが面倒くさそうだったので、普通のActivityです。
public class mainActivity extends Activity{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Switch enableSwitch = (Switch)findViewById(R.id.enableSwitch);
final Spinner selectSpinner = (Spinner)findViewById(R.id.selectSpinner);
final RelativeLayout editBox = (RelativeLayout)findViewById(R.id.editBox);
final Button editButton = (Button)findViewById(R.id.editButton);
setInitialPreferences();
PreferenceUtil prefUtil = new PreferenceUtil(this);
enableSwitch.setChecked(prefUtil.GetBoolean("enable"));
enableSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton arg0, boolean checked) {
PreferenceUtil prefUtil = new PreferenceUtil(mainActivity.this);
prefUtil.SetBoolean("enable", checked);
}
});
selectSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
PreferenceUtil prefUtil = new PreferenceUtil(mainActivity.this);
String selectedItem = parent.getSelectedItem().toString();
prefUtil.SetInt("selectedPosition", position);
if (selectedItem.equals(getString(R.string.select_item_etc))) {
editBox.setVisibility(View.VISIBLE);
prefUtil.SetString("prefix", prefUtil.GetString("inputPrefix"));
} else {
editBox.setVisibility(View.GONE);
if (selectedItem.equals(getString(R.string.select_item_gcall))) {
prefUtil.SetString("prefix", getString(R.string.number_gcall));
} else if (selectedItem.equals(getString(R.string.select_item_rakuten))) {
prefUtil.SetString("prefix", getString(R.string.number_rakuten));
}
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {}
});
selectSpinner.setSelection(prefUtil.GetInt("selectPotision"));
editButton.setText(getString(R.string.edit_button) + " : " + prefUtil.GetString("inputPrefix"));
editButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
final EditText editText = new EditText(mainActivity.this);
PreferenceUtil prefUtil = new PreferenceUtil(mainActivity.this);
editText.setText(prefUtil.GetString("prefix"));
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mainActivity.this);
alertDialog.setTitle(getString(R.string.edit_button));
alertDialog.setView(editText);
alertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
String setText = editText.getText().toString();
PreferenceUtil prefUtil = new PreferenceUtil(mainActivity.this);
prefUtil.SetString("inputPrefix", setText);
prefUtil.SetString("prefix", setText);
editButton.setText(getString(R.string.edit_button) + " : " + setText);
}});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
}});
alertDialog.show();
}
});
}
private void setInitialPreferences() {
PreferenceUtil prefUtil = new PreferenceUtil(this);
if (!prefUtil.GetBoolean("IsSetDefault")) {
prefUtil.SetBoolean("enable", false);
prefUtil.SetInt("selectedPosition", 0);
prefUtil.SetString("prefix", getString(R.string.number_gcall));
prefUtil.SetString("inputPrefix", "");
prefUtil.SetBoolean("dialog", false);
prefUtil.SetBoolean("IsSetDefault", true);
}
}
}
CallReceiver.java
Callを処理するBroadcastReceiverです。注意する点は、新しい call intentを発するともう一度このReceiverを通ること。うまくスルーしないと無限ループに陥ります。私の場合は、緊急電話やフリーダイヤルをスルーすることに加え、すでにプレフィックスが付加されている場合もスルーすることで対策を行いました。
public class CallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase(Intent.ACTION_NEW_OUTGOING_CALL)) {
PreferenceUtil prefUtil = new PreferenceUtil(context);
if (prefUtil.GetBoolean("enable")) {
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
String prefix = prefUtil.GetString("prefix");
if (isExcludeNumber(phoneNumber, prefix)) {
// ignore this process
} else {
// cut the dialed call and redial the new call.
setResultData(null);
Uri uri = Uri.fromParts("tel", prefix + phoneNumber, null);
Intent callIntent = new Intent(Intent.ACTION_CALL, uri);
callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(callIntent);
}
}
}
}
// free call, emergency call, prefix added
private boolean isExcludeNumber(String phoneNumber, String prefix) {
if (!prefix.isEmpty()) {
if (phoneNumber.length() == 3 && phoneNumber.substring(0, 1).equals("1")) {
return true;
} else {
String[] specialNumbers = {"0120", "0800", "0070", "0077", "0088", "0570", "0063", "003768", prefix};
for (String specialNumber:specialNumbers) {
if (phoneNumber.length() >= specialNumber.length()) {
if (phoneNumber.substring(0, specialNumber.length()).equals(specialNumber)) {
return true;
}
}
}
}
}
return false;
}
}
PreferenceUtil.java
Preferenceを簡単に使うためのclassです。直接書く場合は必要ありません。
public class PreferenceUtil {
private SharedPreferences sp;
protected PreferenceUtil(Context context) {
sp = context.getSharedPreferences("alarm", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
}
public void SetString(String strKey, String strVal) {
SharedPreferences.Editor editor = sp.edit();
editor.putString(strKey, strVal);
editor.commit();
}
public String GetString(String strKey) {
return sp.getString(strKey, "");
}
public void SetInt(String strKey, int intVal) {
SharedPreferences.Editor editor = sp.edit();
editor.putInt(strKey, intVal);
editor.commit();
}
public int GetInt(String strKey) {
return sp.getInt(strKey, -1);
}
public void SetBoolean(String strKey, Boolean booleanVal) {
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean(strKey, booleanVal);
editor.commit();
}
public Boolean GetBoolean(String strKey) {
return sp.getBoolean(strKey, false);
}
public void SetFloat(String strKey, Float FloatVal) {
SharedPreferences.Editor editor = sp.edit();
editor.putFloat(strKey, FloatVal);
editor.commit();
}
public Float GetFloat(String strKey) {
return sp.getFloat(strKey, 0.0f);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="@dimen/prefs_height"
android:layout_marginBottom="@dimen/prefs_bottom"
android:layout_marginLeft="@dimen/prefs_left"
android:layout_marginRight="@dimen/prefs_right" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="@string/enable"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Switch
android:id="@+id/enableSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="@dimen/prefs_height"
android:layout_marginBottom="@dimen/prefs_bottom"
android:layout_marginLeft="@dimen/prefs_left"
android:layout_marginRight="@dimen/prefs_right" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:text="@string/select"
android:textAppearance="?android:attr/textAppearanceMedium" />
<Spinner
android:id="@+id/selectSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:entries="@array/select_list" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/editBox"
android:layout_width="wrap_content"
android:layout_height="@dimen/prefs_height"
android:layout_marginBottom="@dimen/prefs_bottom"
android:layout_marginLeft="@dimen/prefs_left"
android:layout_marginRight="@dimen/prefs_right" >
<Button
android:id="@+id/editButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="@string/edit_button" />
</RelativeLayout>
</LinearLayout>
AndroidManifest.xml
call intentを発するためのpermissionが必要です。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mikotomoti.zeropluscall"
android:versionCode="1"
android:versionName="1.0.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.mikotomoti.zeropluscall.mainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.mikotomoti.zeropluscall.CallReceiver">
<intent-filter android:priority="1">
<action
android:name="android.intent.action.NEW_OUTGOING_CALL"></action>
</intent-filter>
</receiver>
</application>
</manifest>
strings.xml
SpinnerにAdapterを介してアイテムを投入するのは少しコードが煩雑になります。アイテムが固定値の場合、string-arrayをレイアウトで入れてしまうほうが簡単です。
<resources>
<string name="app_name">00 Plus Call</string>
<string name="title_setting">設定</string>
<string name="enable">有効</string>
<string name="select">通話会社の選択</string>
<string name="edit_button">番号を入力</string>
<string name="dialog">確認画面の表示</string>
<string-array name="select_list">
<item>G-Call</item>
<item>楽天でんわ</item>
<item>その他</item>
</string-array>
<string name="select_item_gcall">G-Call</string> <!-- 判定に使用するので上のリストと同じにすること -->
<string name="select_item_rakuten">楽天でんわ</string> <!-- 判定に使用するので上のリストと同じにすること -->
<string name="select_item_etc">その他</string> <!-- 判定に使用するので上のリストと同じにすること -->
<string name="number_gcall">0063</string>
<string name="number_rakuten">003768</string>
</resources>
0 件のコメント:
コメントを投稿