From 47c51fb16f344247a90ab0d6cc4b4cec939d298c Mon Sep 17 00:00:00 2001 From: aJIEw Date: Wed, 21 Apr 2021 15:38:18 +0800 Subject: [PATCH 1/8] Update README.md update blog link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a39f5aa..86798a3 100644 --- a/README.md +++ b/README.md @@ -18,4 +18,4 @@ This project shows you how to make your app as the default phone call app and ma ![listen_phone_call](media/listen_phone_call.gif) -原文链接:[安卓代替系统默认电话应用 (Android 6.0+) 与电话状态监听](https://ajiew.github.io/2018-08-11-android-replace-default-phone-app-and-listen-phone-calls/) +原文链接:[安卓代替系统默认电话应用 (Android 6.0+) 与电话状态监听](https://ajiew.github.io/android-phone-call-app-and-listen-phone-calls/) From 7572d49aa639ff8d14b2e62e9a2580d14657d595 Mon Sep 17 00:00:00 2001 From: "aaron.chen" Date: Fri, 4 Jun 2021 18:41:27 +0800 Subject: [PATCH 2/8] upgrade android gradle plugin --- .idea/compiler.xml | 6 ++++++ .idea/jarRepositories.xml | 5 +++++ .idea/misc.xml | 12 +++++++++--- .idea/runConfigurations.xml | 1 + build.gradle | 6 +++--- gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 54417 bytes gradle/wrapper/gradle-wrapper.properties | 3 +-- 7 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 .idea/compiler.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml index f04d60e..0912bd8 100644 --- a/.idea/jarRepositories.xml +++ b/.idea/jarRepositories.xml @@ -41,5 +41,10 @@ - + diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml index 7f68460..e497da9 100644 --- a/.idea/runConfigurations.xml +++ b/.idea/runConfigurations.xml @@ -3,6 +3,7 @@ \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index a55e7a1..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index b589d56..0000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index ed25cec..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml deleted file mode 100644 index f5371de..0000000 --- a/.idea/deploymentTargetSelector.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/dictionaries/Cerie.xml b/.idea/dictionaries/Cerie.xml deleted file mode 100644 index 560a4bc..0000000 --- a/.idea/dictionaries/Cerie.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 639c779..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml deleted file mode 100644 index 0912bd8..0000000 --- a/.idea/jarRepositories.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/markdown-navigator.xml b/.idea/markdown-navigator.xml deleted file mode 100644 index 4e63b3e..0000000 --- a/.idea/markdown-navigator.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/markdown-navigator/profiles_settings.xml b/.idea/markdown-navigator/profiles_settings.xml deleted file mode 100644 index db06266..0000000 --- a/.idea/markdown-navigator/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml deleted file mode 100644 index f8051a6..0000000 --- a/.idea/migrations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 021d59a..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 16660f1..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6975cb2..ea7f20a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,6 +25,7 @@ tools:ignore="AllowBackup"> @@ -81,4 +82,4 @@ - \ No newline at end of file + diff --git a/app/src/main/java/com/ajiew/phonecallapp/ActivityStack.java b/app/src/main/java/com/ajiew/phonecallapp/ActivityStack.java index 019acf0..00a822d 100644 --- a/app/src/main/java/com/ajiew/phonecallapp/ActivityStack.java +++ b/app/src/main/java/com/ajiew/phonecallapp/ActivityStack.java @@ -3,6 +3,7 @@ import android.app.Activity; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; @@ -10,14 +11,16 @@ public class ActivityStack { private static final ActivityStack INSTANCE = new ActivityStack(); - private List activities = new ArrayList<>(); + private final List activities = new ArrayList<>(); public static ActivityStack getInstance() { return INSTANCE; } public void addActivity(Activity activity) { - activities.add(activity); + if (activity != null) { + activities.add(activity); + } } public Activity getTopActivity() { @@ -41,18 +44,27 @@ public void finishActivity(Activity activity) { } public void finishActivity(Class activityClass) { - for (Activity activity : activities) { - if (activity.getClass().equals(activityClass)) { - finishActivity(activity); + if (activityClass == null) { + return; + } + + Iterator iterator = activities.iterator(); + while (iterator.hasNext()) { + Activity activity = iterator.next(); + if (activity != null && activity.getClass().equals(activityClass)) { + iterator.remove(); + activity.finish(); } } } public void finishAllActivity() { - if (!activities.isEmpty()) { - for (Activity activity : activities) { + Iterator iterator = activities.iterator(); + while (iterator.hasNext()) { + Activity activity = iterator.next(); + iterator.remove(); + if (activity != null) { activity.finish(); - activities.remove(activity); } } } diff --git a/app/src/main/java/com/ajiew/phonecallapp/MainActivity.java b/app/src/main/java/com/ajiew/phonecallapp/MainActivity.java index baa8b98..681c920 100644 --- a/app/src/main/java/com/ajiew/phonecallapp/MainActivity.java +++ b/app/src/main/java/com/ajiew/phonecallapp/MainActivity.java @@ -49,6 +49,18 @@ public class MainActivity extends AppCompatActivity { } }); + private final ActivityResultLauncher phoneStatePermissionLauncher = registerForActivityResult( + new ActivityResultContracts.RequestPermission(), granted -> { + if (granted) { + if (switchListenCall != null && switchListenCall.isChecked()) { + startCallListenerService(); + } + } else { + Toast.makeText(this, "缺少获取电话状态权限", Toast.LENGTH_SHORT).show(); + setSwitchListenCallChecked(false); + } + }); + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { EdgeToEdge.enable(this); @@ -69,6 +81,12 @@ private void initView() { // Android 10 之后需要通过 RoleManager 修改默认电话应用 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) { RoleManager roleManager = (RoleManager) getSystemService(Context.ROLE_SERVICE); + if (roleManager == null + || !roleManager.isRoleAvailable(RoleManager.ROLE_DIALER)) { + Toast.makeText(this, "当前设备不支持设置默认电话应用", Toast.LENGTH_SHORT).show(); + switchPhoneCall.setChecked(false); + return; + } Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER); dialerRequestLauncher.launch(intent); } else { @@ -105,22 +123,40 @@ private void initView() { boolean granted = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED; if (isChecked && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && !granted) { - Toast.makeText(this, "缺少获取电话状态权限", Toast.LENGTH_SHORT).show(); + phoneStatePermissionLauncher.launch(Manifest.permission.READ_PHONE_STATE); return; } - Intent callListener = new Intent(MainActivity.this, CallListenerService.class); if (isChecked) { - startService(callListener); - Toast.makeText(this, "电话监听服务已开启", Toast.LENGTH_SHORT).show(); + startCallListenerService(); } else { - stopService(callListener); - Toast.makeText(this, "电话监听服务已关闭", Toast.LENGTH_SHORT).show(); + stopCallListenerService(); } }; switchListenCall.setOnCheckedChangeListener(switchCallCheckChangeListener); } + private void startCallListenerService() { + Intent callListener = new Intent(MainActivity.this, CallListenerService.class); + startService(callListener); + Toast.makeText(this, "电话监听服务已开启", Toast.LENGTH_SHORT).show(); + } + + private void stopCallListenerService() { + Intent callListener = new Intent(MainActivity.this, CallListenerService.class); + stopService(callListener); + Toast.makeText(this, "电话监听服务已关闭", Toast.LENGTH_SHORT).show(); + } + + private void setSwitchListenCallChecked(boolean checked) { + if (switchListenCall == null) { + return; + } + switchListenCall.setOnCheckedChangeListener(null); + switchListenCall.setChecked(checked); + switchListenCall.setOnCheckedChangeListener(switchCallCheckChangeListener); + } + private void askForDrawOverlay() { AlertDialog alertDialog = new AlertDialog.Builder(this) .setTitle("允许显示悬浮框") @@ -132,11 +168,12 @@ private void askForDrawOverlay() { .setNegativeButton("稍后再说", (dialog, which) -> dialog.dismiss()) .create(); - //noinspection ConstantConditions - alertDialog.getWindow().setFlags( - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); alertDialog.show(); + if (alertDialog.getWindow() != null) { + alertDialog.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); + } } /** @@ -187,7 +224,8 @@ public boolean isServiceRunning(Class serviceClass) { for (ActivityManager.RunningServiceInfo service : manager.getRunningServices( Integer.MAX_VALUE)) { - if (serviceClass.getName().equals(service.service.getClassName())) { + if (service != null && service.service != null + && serviceClass.getName().equals(service.service.getClassName())) { return true; } } diff --git a/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/CallListenerService.java b/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/CallListenerService.java index b50bb4b..8da5db6 100644 --- a/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/CallListenerService.java +++ b/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/CallListenerService.java @@ -7,10 +7,7 @@ import android.graphics.PixelFormat; import android.os.Build; import android.os.IBinder; -import android.telephony.PhoneStateListener; -import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; -import android.text.TextUtils; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -20,6 +17,7 @@ import android.widget.FrameLayout; import android.widget.TextView; +import androidx.core.content.ContextCompat; import androidx.annotation.Nullable; import com.ajiew.phonecallapp.MainActivity; @@ -45,9 +43,11 @@ public class CallListenerService extends Service { public void onCreate() { super.onCreate(); - initPhoneStateListener(); - - initPhoneCallView(); + if (initPhoneCallView()) { + initPhoneStateListener(); + } else { + stopSelf(); + } } @Nullable @@ -62,10 +62,15 @@ public IBinder onBind(Intent intent) { private void initPhoneStateListener() { phoneStateListenerCompat = new PhoneStateListenerCompat() { @Override - public void onCallStateChanged(int state) { + public void onCallStateChanged(int state, String phoneNumber) { + if (phoneNumber != null && !phoneNumber.isEmpty()) { + callNumber = phoneNumber; + } + switch (state) { case TelephonyManager.CALL_STATE_IDLE: // 待机,即无电话时,挂断时触发 dismiss(); + callNumber = null; break; case TelephonyManager.CALL_STATE_RINGING: // 响铃,来电时触发 @@ -88,15 +93,16 @@ public void onCallStateChanged(int state) { phoneStateListenerCompat.startListening(this); } - private void initPhoneCallView() { + private boolean initPhoneCallView() { windowManager = (WindowManager) getApplicationContext() .getSystemService(Context.WINDOW_SERVICE); - int width = windowManager.getDefaultDisplay().getWidth(); - int height = windowManager.getDefaultDisplay().getHeight(); + if (windowManager == null) { + return false; + } params = new WindowManager.LayoutParams(); params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; - params.width = width; + params.width = WindowManager.LayoutParams.MATCH_PARENT; params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; @@ -136,22 +142,30 @@ public boolean dispatchKeyEvent(KeyEvent event) { } }; - phoneCallView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)) - .inflate(R.layout.view_phone_call, interceptorLayout); + LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); + if (layoutInflater == null) { + return false; + } + + phoneCallView = layoutInflater.inflate(R.layout.view_phone_call, interceptorLayout); tvCallNumber = phoneCallView.findViewById(R.id.tv_call_number); btnOpenApp = phoneCallView.findViewById(R.id.btn_open_app); + if (tvCallNumber == null || btnOpenApp == null) { + return false; + } btnOpenApp.setOnClickListener(v -> { Intent intent = new Intent(getApplicationContext(), MainActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); CallListenerService.this.startActivity(intent); }); + return true; } /** * 显示顶级弹框展示通话信息 */ private void show() { - if (!hasShown) { + if (!hasShown && windowManager != null && phoneCallView != null && params != null) { windowManager.addView(phoneCallView, params); hasShown = true; } @@ -161,7 +175,7 @@ private void show() { * 取消显示 */ private void dismiss() { - if (hasShown) { + if (hasShown && windowManager != null && phoneCallView != null) { windowManager.removeView(phoneCallView); isCallingIn = false; hasShown = false; @@ -169,15 +183,20 @@ private void dismiss() { } private void updateUI() { - tvCallNumber.setText(formatPhoneNumber(callNumber)); + if (callNumber != null && !callNumber.isEmpty()) { + tvCallNumber.setText(formatPhoneNumber(callNumber)); + } int callTypeDrawable = isCallingIn ? R.drawable.ic_phone_call_in : R.drawable.ic_phone_call_out; tvCallNumber.setCompoundDrawablesWithIntrinsicBounds(null, null, - getResources().getDrawable(callTypeDrawable), null); + ContextCompat.getDrawable(this, callTypeDrawable), null); } public static String formatPhoneNumber(String phoneNum) { - if (!TextUtils.isEmpty(phoneNum) && phoneNum.length() == 11) { + if (phoneNum == null || phoneNum.isEmpty()) { + return "未知号码"; + } + if (phoneNum.length() == 11) { return phoneNum.substring(0, 3) + "-" + phoneNum.substring(3, 7) + "-" + phoneNum.substring(7); @@ -189,6 +208,8 @@ public static String formatPhoneNumber(String phoneNum) { public void onDestroy() { super.onDestroy(); - phoneStateListenerCompat.stopListening(this); + if (phoneStateListenerCompat != null) { + phoneStateListenerCompat.stopListening(this); + } } } diff --git a/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/PhoneStateListenerCompat.java b/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/PhoneStateListenerCompat.java index 598b32b..e6c4fca 100644 --- a/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/PhoneStateListenerCompat.java +++ b/app/src/main/java/com/ajiew/phonecallapp/listenphonecall/PhoneStateListenerCompat.java @@ -4,78 +4,80 @@ import android.os.Build; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; -import android.util.Log; import androidx.annotation.RequiresApi; /** - * 新的电话状态监听器,适配 {@link android.telephony.TelephonyCallback} 以及老版本的 {@link PhoneStateListener} + * 电话状态监听器,API 31+ 使用 {@link android.telephony.TelephonyCallback.CallStateListener}。 * * @author aJIEw * Created on: 2025/5/6 16:45 */ public abstract class PhoneStateListenerCompat { private PhoneStateListener phoneStateListener; - private TelephonyCallback telephonyCallback; + private CallStateTelephonyCallback callStateListener; + @SuppressWarnings("deprecation") public void startListening(Context context) { TelephonyManager tm = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); + if (tm == null) { + return; + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - telephonyCallback = new TelephonyCallback() { + callStateListener = new CallStateTelephonyCallback() { @Override public void onCallStateChanged(int state) { - Log.d(PhoneStateListenerCompat.class.getSimpleName(), "onCallStateChanged: "); - PhoneStateListenerCompat.this.onCallStateChanged(state); + PhoneStateListenerCompat.this.onCallStateChanged(state, null); } }; - tm.registerTelephonyCallback(context.getMainExecutor(), telephonyCallback); + tm.registerTelephonyCallback(context.getMainExecutor(), callStateListener); } else { phoneStateListener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String phoneNumber) { - PhoneStateListenerCompat.this.onCallStateChanged(state); + PhoneStateListenerCompat.this.onCallStateChanged(state, phoneNumber); } }; - tm.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + startLegacyListening(tm, phoneStateListener); } } public void stopListening(Context context) { TelephonyManager tm = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); + if (tm == null) { + return; + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - if (telephonyCallback != null) { - tm.unregisterTelephonyCallback(telephonyCallback); + if (callStateListener != null) { + tm.unregisterTelephonyCallback(callStateListener); + callStateListener = null; } } else { if (phoneStateListener != null) { - tm.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE); + stopLegacyListening(tm, phoneStateListener); + phoneStateListener = null; } } } - public abstract void onCallStateChanged(int state); + @SuppressWarnings("deprecation") + private void startLegacyListening(TelephonyManager tm, PhoneStateListener listener) { + tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); + } + + @SuppressWarnings("deprecation") + private void stopLegacyListening(TelephonyManager tm, PhoneStateListener listener) { + tm.listen(listener, PhoneStateListener.LISTEN_NONE); + } + + public abstract void onCallStateChanged(int state, String phoneNumber); } @RequiresApi(api = Build.VERSION_CODES.S) -class TelephonyCallback extends android.telephony.TelephonyCallback +abstract class CallStateTelephonyCallback extends android.telephony.TelephonyCallback implements android.telephony.TelephonyCallback.CallStateListener { - - @Override - public void onCallStateChanged(int state) { - switch (state) { - case TelephonyManager.CALL_STATE_IDLE: - // 空闲状态 - break; - case TelephonyManager.CALL_STATE_RINGING: - // 来电响铃 - break; - case TelephonyManager.CALL_STATE_OFFHOOK: - // 通话中 - break; - } - } } diff --git a/app/src/main/java/com/ajiew/phonecallapp/phonecallui/PhoneCallService.java b/app/src/main/java/com/ajiew/phonecallapp/phonecallui/PhoneCallService.java index 26eb6f5..5dde231 100644 --- a/app/src/main/java/com/ajiew/phonecallapp/phonecallui/PhoneCallService.java +++ b/app/src/main/java/com/ajiew/phonecallapp/phonecallui/PhoneCallService.java @@ -1,5 +1,6 @@ package com.ajiew.phonecallapp.phonecallui; +import android.net.Uri; import android.os.Build; import android.telecom.Call; import android.telecom.InCallService; @@ -42,6 +43,9 @@ public void onStateChanged(Call call, int state) { @Override public void onCallAdded(Call call) { super.onCallAdded(call); + if (call == null) { + return; + } call.registerCallback(callback); PhoneCallManager.call = call; @@ -55,8 +59,7 @@ public void onCallAdded(Call call) { } if (callType != null) { - Call.Details details = call.getDetails(); - String phoneNumber = details.getHandle().getSchemeSpecificPart(); + String phoneNumber = getPhoneNumber(call); PhoneCallActivity.actionStart(this, phoneNumber, callType); } } @@ -64,11 +67,29 @@ public void onCallAdded(Call call) { @Override public void onCallRemoved(Call call) { super.onCallRemoved(call); + if (call == null) { + PhoneCallManager.call = null; + return; + } call.unregisterCallback(callback); PhoneCallManager.call = null; } + private String getPhoneNumber(Call call) { + Call.Details details = call.getDetails(); + if (details == null) { + return null; + } + + Uri handle = details.getHandle(); + if (handle == null) { + return null; + } + + return handle.getSchemeSpecificPart(); + } + public enum CallType { CALL_IN, CALL_OUT, diff --git a/app/src/test/java/com/ajiew/phonecallapp/ActivityStackTest.java b/app/src/test/java/com/ajiew/phonecallapp/ActivityStackTest.java new file mode 100644 index 0000000..edd0e13 --- /dev/null +++ b/app/src/test/java/com/ajiew/phonecallapp/ActivityStackTest.java @@ -0,0 +1,41 @@ +package com.ajiew.phonecallapp; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.app.Activity; + +import org.junit.After; +import org.junit.Test; + +public class ActivityStackTest { + + @After + public void tearDown() { + ActivityStack.getInstance().finishAllActivity(); + } + + @Test + public void finishActivityByClass_removesMatchingActivitiesWithoutCrash() { + TestActivity firstActivity = new TestActivity(); + TestActivity secondActivity = new TestActivity(); + + ActivityStack.getInstance().addActivity(firstActivity); + ActivityStack.getInstance().addActivity(secondActivity); + + ActivityStack.getInstance().finishActivity(TestActivity.class); + + assertTrue(firstActivity.finished); + assertTrue(secondActivity.finished); + assertNull(ActivityStack.getInstance().getTopActivity()); + } + + public static class TestActivity extends Activity { + boolean finished; + + @Override + public void finish() { + finished = true; + } + } +} diff --git a/app/src/test/java/com/ajiew/phonecallapp/listenphonecall/CallListenerServiceTest.java b/app/src/test/java/com/ajiew/phonecallapp/listenphonecall/CallListenerServiceTest.java new file mode 100644 index 0000000..4331231 --- /dev/null +++ b/app/src/test/java/com/ajiew/phonecallapp/listenphonecall/CallListenerServiceTest.java @@ -0,0 +1,28 @@ +package com.ajiew.phonecallapp.listenphonecall; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class CallListenerServiceTest { + + @Test + public void formatPhoneNumber_returnsUnknownWhenNull() { + assertEquals("未知号码", CallListenerService.formatPhoneNumber(null)); + } + + @Test + public void formatPhoneNumber_returnsUnknownWhenEmpty() { + assertEquals("未知号码", CallListenerService.formatPhoneNumber("")); + } + + @Test + public void formatPhoneNumber_formatsElevenDigitNumber() { + assertEquals("133-8892-9579", CallListenerService.formatPhoneNumber("13388929579")); + } + + @Test + public void formatPhoneNumber_keepsNonElevenDigitNumber() { + assertEquals("10086", CallListenerService.formatPhoneNumber("10086")); + } +}