基本电话接听与拨打功能完成
This commit is contained in:
		| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Thu Feb 20 09:27:14 GMT 2025 | ||||
| #Thu Feb 20 22:09:07 GMT 2025 | ||||
| stageCount=0 | ||||
| libraryProject=winboll-shared | ||||
| baseVersion=1.0 | ||||
| publishVersion=1.0.0 | ||||
| buildCount=99 | ||||
| buildCount=126 | ||||
| baseBetaVersion=1.0.1 | ||||
|   | ||||
| @@ -9,6 +9,24 @@ | ||||
|     <!-- 拨打电话 --> | ||||
|     <uses-permission android:name="android.permission.CALL_PHONE"/> | ||||
|  | ||||
|     <!-- 读取手机状态和身份 --> | ||||
|     <uses-permission android:name="android.permission.READ_PHONE_STATE"/> | ||||
|  | ||||
|     <!-- 修改系统设置 --> | ||||
|     <uses-permission android:name="android.permission.WRITE_SETTINGS"/> | ||||
|  | ||||
|     <!-- 重新设置外拨电话的路径 --> | ||||
|     <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/> | ||||
|  | ||||
|     <!-- 读取联系人 --> | ||||
|     <uses-permission android:name="android.permission.READ_CONTACTS"/> | ||||
|  | ||||
|     <!-- 修改您的通讯录 --> | ||||
|     <uses-permission android:name="android.permission.WRITE_CONTACTS"/> | ||||
|  | ||||
|     <!-- 此应用可显示在其他应用上方 --> | ||||
|     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> | ||||
|  | ||||
|     <application | ||||
|         android:name=".App" | ||||
|         android:allowBackup="true" | ||||
| @@ -32,18 +50,44 @@ | ||||
|             </intent-filter> | ||||
|  | ||||
|         </activity> | ||||
|          | ||||
|  | ||||
|         <provider | ||||
|             android:name="androidx.core.content.FileProvider" | ||||
|             android:authorities="${applicationId}.fileprovider" | ||||
|             android:exported="false" | ||||
|             android:grantUriPermissions="true"> | ||||
|         <activity | ||||
|             android:name=".activities.CallActivity" | ||||
|             android:label="CallActivity" | ||||
|             android:launchMode="singleTask" | ||||
|             android:exported="true"> | ||||
|  | ||||
|             <meta-data | ||||
|                 android:name="android.support.FILE_PROVIDER_PATHS" | ||||
|                 android:resource="@xml/studio_provider"/> | ||||
|         </activity> | ||||
|  | ||||
|         </provider> | ||||
|         <activity | ||||
|             android:name=".phonecallui.PhoneCallActivity" | ||||
|             android:launchMode="singleInstance" | ||||
|             android:exported="true"> | ||||
|  | ||||
|             <intent-filter> | ||||
|  | ||||
|                 <action android:name="android.intent.action.DIAL"/> | ||||
|  | ||||
|                 <action android:name="android.intent.action.VIEW"/> | ||||
|  | ||||
|                 <category android:name="android.intent.category.DEFAULT"/> | ||||
|  | ||||
|                 <category android:name="android.intent.category.BROWSABLE"/> | ||||
|  | ||||
|                 <data android:scheme="tel"/> | ||||
|  | ||||
|             </intent-filter> | ||||
|  | ||||
|             <intent-filter> | ||||
|  | ||||
|                 <action android:name="android.intent.action.DIAL"/> | ||||
|  | ||||
|                 <category android:name="android.intent.category.DEFAULT"/> | ||||
|  | ||||
|             </intent-filter> | ||||
|  | ||||
|         </activity> | ||||
|  | ||||
|         <service | ||||
|             android:name="cc.winboll.studio.contacts.services.MainService" | ||||
| @@ -51,7 +95,37 @@ | ||||
|  | ||||
|         <service android:name="cc.winboll.studio.contacts.services.AssistantService"/> | ||||
|  | ||||
|         <receiver android:name="cc.winboll.studio.contacts.receivers.MainReceiver"> | ||||
|         <service | ||||
|             android:name=".phonecallui.PhoneCallService" | ||||
|             android:permission="android.permission.BIND_INCALL_SERVICE" | ||||
|             android:exported="false"> | ||||
|  | ||||
|             <meta-data | ||||
|                 android:name="android.telecom.IN_CALL_SERVICE_UI" | ||||
|                 android:value="true"/> | ||||
|  | ||||
|             <intent-filter> | ||||
|  | ||||
|                 <action android:name="android.telecom.InCallService"/> | ||||
|  | ||||
|             </intent-filter> | ||||
|  | ||||
|         </service> | ||||
|  | ||||
|         <service | ||||
|             android:name=".listenphonecall.CallListenerService" | ||||
|             android:enabled="true" | ||||
|             android:exported="false"> | ||||
|  | ||||
|             <intent-filter android:priority="1000"> | ||||
|  | ||||
|                 <action android:name=".service.CallShowService"/> | ||||
|  | ||||
|             </intent-filter> | ||||
|  | ||||
|         </service> | ||||
|  | ||||
|         <receiver android:name=".receivers.MainReceiver"> | ||||
|  | ||||
|             <intent-filter> | ||||
|  | ||||
| @@ -91,8 +165,20 @@ | ||||
|  | ||||
|         </receiver> | ||||
|  | ||||
|         <activity android:name="cc.winboll.studio.contacts.activities.CallActivity"/> | ||||
|         <provider | ||||
|             android:name="androidx.core.content.FileProvider" | ||||
|             android:authorities="${applicationId}.fileprovider" | ||||
|             android:exported="false" | ||||
|             android:grantUriPermissions="true"> | ||||
|  | ||||
|             <meta-data | ||||
|                 android:name="android.support.FILE_PROVIDER_PATHS" | ||||
|                 android:resource="@xml/studio_provider"/> | ||||
|  | ||||
|         </provider> | ||||
|  | ||||
|         <activity android:name="cc.winboll.studio.contacts.activities.SettingsActivity"/> | ||||
|  | ||||
|     </application> | ||||
|  | ||||
| </manifest> | ||||
| </manifest> | ||||
|   | ||||
| @@ -0,0 +1,59 @@ | ||||
| package cc.winboll.studio.contacts; | ||||
|  | ||||
| import android.app.Activity; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
|  | ||||
| public class ActivityStack { | ||||
|  | ||||
|     private static final ActivityStack INSTANCE = new ActivityStack(); | ||||
|  | ||||
|     private List<Activity> activities = new ArrayList<>(); | ||||
|  | ||||
|     public static ActivityStack getInstance() { | ||||
|         return INSTANCE; | ||||
|     } | ||||
|  | ||||
|     public void addActivity(Activity activity) { | ||||
|         activities.add(activity); | ||||
|     } | ||||
|  | ||||
|     public Activity getTopActivity() { | ||||
|         if (activities.isEmpty()) { | ||||
|             return null; | ||||
|         } | ||||
|         return activities.get(activities.size() - 1); | ||||
|     } | ||||
|  | ||||
|     public void finishTopActivity() { | ||||
|         if (!activities.isEmpty()) { | ||||
|             activities.remove(activities.size() - 1).finish(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void finishActivity(Activity activity) { | ||||
|         if (activity != null) { | ||||
|             activities.remove(activity); | ||||
|             activity.finish(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void finishActivity(Class activityClass) { | ||||
|         for (Activity activity : activities) { | ||||
|             if (activity.getClass().equals(activityClass)) { | ||||
|                 finishActivity(activity); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void finishAllActivity() { | ||||
|         if (!activities.isEmpty()) { | ||||
|             for (Activity activity : activities) { | ||||
|                 activity.finish(); | ||||
|                 activities.remove(activity); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,30 +1,52 @@ | ||||
| package cc.winboll.studio.contacts; | ||||
|  | ||||
| import android.Manifest; | ||||
| import android.annotation.SuppressLint; | ||||
| import android.app.Activity; | ||||
| import android.app.ActivityManager; | ||||
| import android.app.role.RoleManager; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.net.Uri; | ||||
| import android.os.Build; | ||||
| import android.os.Bundle; | ||||
| import android.provider.Settings; | ||||
| import android.telecom.TelecomManager; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.Menu; | ||||
| import android.view.MenuItem; | ||||
| import android.view.View; | ||||
| import android.view.WindowManager; | ||||
| import android.widget.CheckBox; | ||||
| import com.google.android.material.tabs.TabLayout; | ||||
| import android.widget.CompoundButton; | ||||
| import android.widget.ImageView; | ||||
| import android.widget.LinearLayout; | ||||
| import android.widget.Switch; | ||||
| import android.widget.Toast; | ||||
| import androidx.appcompat.app.AlertDialog; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import androidx.core.content.ContextCompat; | ||||
| import androidx.viewpager.widget.ViewPager; | ||||
| import cc.winboll.studio.contacts.R; | ||||
| import cc.winboll.studio.contacts.activities.CallActivity; | ||||
| import cc.winboll.studio.contacts.adapters.MyPagerAdapter; | ||||
| import cc.winboll.studio.contacts.beans.MainServiceBean; | ||||
| import cc.winboll.studio.contacts.services.MainService; | ||||
| import cc.winboll.studio.libappbase.LogUtils; | ||||
| import cc.winboll.studio.libappbase.LogView; | ||||
| import cc.winboll.studio.libapputils.app.IWinBollActivity; | ||||
| import cc.winboll.studio.libapputils.app.WinBollActivityManager; | ||||
| import cc.winboll.studio.libapputils.bean.APPInfo; | ||||
| import cc.winboll.studio.libapputils.view.YesNoAlertDialog; | ||||
| import android.widget.ImageView; | ||||
| import android.view.View; | ||||
| import cc.winboll.studio.contacts.listenphonecall.CallListenerService; | ||||
| import com.google.android.material.tabs.TabLayout; | ||||
| import java.lang.reflect.Field; | ||||
| import java.util.ArrayList; | ||||
| import android.view.LayoutInflater; | ||||
| import android.widget.LinearLayout; | ||||
| import java.util.List; | ||||
| import cc.winboll.studio.contacts.activities.CallActivity; | ||||
| import android.content.DialogInterface; | ||||
| import cc.winboll.studio.contacts.activities.SettingsActivity; | ||||
|  | ||||
| final public class MainActivity extends AppCompatActivity implements IWinBollActivity, ViewPager.OnPageChangeListener, View.OnClickListener { | ||||
|  | ||||
| @@ -48,6 +70,8 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
|     LinearLayout linearLayout;//下标所在在LinearLayout布局里 | ||||
|     int currentPoint = 0;//当前被选中中页面的下标 | ||||
|  | ||||
|     private static final int DIALER_REQUEST_CODE = 1; | ||||
|  | ||||
|     @Override | ||||
|     public AppCompatActivity getActivity() { | ||||
|         return this; | ||||
| @@ -90,7 +114,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
|         getSupportActionBar().setSubtitle(getTag()); | ||||
|  | ||||
|         initData(); | ||||
|         initView();//调用初始化视图方法 | ||||
|         initView(); | ||||
|         //initPoint();//调用初始化导航原点的方法 | ||||
|         viewPager.addOnPageChangeListener(this);//滑动事件 | ||||
|  | ||||
| @@ -116,9 +140,9 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
| //                    } | ||||
| //                } | ||||
| //            }); | ||||
|         MainService.startMainService(MainActivity.this); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     //初始化view,即显示的图片 | ||||
|     void initView() { | ||||
|         viewPager = findViewById(R.id.activitymainViewPager1); | ||||
| @@ -311,6 +335,10 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
|             Intent intent = new Intent(this, CallActivity.class); | ||||
|             startActivity(intent); | ||||
|             //WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class); | ||||
|         } else if (item.getItemId() == R.id.item_settings) { | ||||
|             Intent intent = new Intent(this, SettingsActivity.class); | ||||
|             startActivity(intent); | ||||
|             //WinBollActivityManager.getInstance(this).startWinBollActivity(this, CallActivity.class); | ||||
|         } | ||||
| //        } else  | ||||
| //        if (item.getItemId() == R.id.item_exit) { | ||||
| @@ -320,20 +348,59 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct | ||||
|         return super.onOptionsItemSelected(item); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     @Override | ||||
|     protected void onResume() { | ||||
|         super.onResume(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Android M 及以上检查是否是系统默认电话应用 | ||||
|      */ | ||||
|     public boolean isDefaultPhoneCallApp() { | ||||
|         if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|             TelecomManager manger = (TelecomManager) getSystemService(TELECOM_SERVICE); | ||||
|             if (manger != null && manger.getDefaultDialerPackage() != null) { | ||||
|                 return manger.getDefaultDialerPackage().equals(getPackageName()); | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     public boolean isServiceRunning(Class<?> serviceClass) { | ||||
|         ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); | ||||
|         if (manager == null) return false; | ||||
|  | ||||
|         for (ActivityManager.RunningServiceInfo service : manager.getRunningServices( | ||||
|             Integer.MAX_VALUE)) { | ||||
|             if (serviceClass.getName().equals(service.service.getClassName())) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onActivityResult(int requestCode, int resultCode, Intent data) { | ||||
|         switch (resultCode) { | ||||
|             case REQUEST_HOME_ACTIVITY : { | ||||
|                     LogUtils.d(TAG, "REQUEST_HOME_ACTIVITY"); | ||||
|                     break; | ||||
|                 } | ||||
|             case REQUEST_ABOUT_ACTIVITY : { | ||||
|                     LogUtils.d(TAG, "REQUEST_ABOUT_ACTIVITY"); | ||||
|                     break; | ||||
|                 } | ||||
|             default : { | ||||
|                     super.onActivityResult(requestCode, resultCode, data); | ||||
|                 } | ||||
| //        switch (resultCode) { | ||||
| //            case REQUEST_HOME_ACTIVITY : { | ||||
| //                    LogUtils.d(TAG, "REQUEST_HOME_ACTIVITY"); | ||||
| //                    break; | ||||
| //                } | ||||
| //            case REQUEST_ABOUT_ACTIVITY : { | ||||
| //                    LogUtils.d(TAG, "REQUEST_ABOUT_ACTIVITY"); | ||||
| //                    break; | ||||
| //                } | ||||
| //            default : { | ||||
| //                    super.onActivityResult(requestCode, resultCode, data); | ||||
| //                } | ||||
| //        } | ||||
|         if (requestCode == DIALER_REQUEST_CODE) { | ||||
|             if (resultCode == Activity.RESULT_OK) { | ||||
|                 Toast.makeText(MainActivity.this, getString(R.string.app_name) + " 已成为默认电话应用", | ||||
|                                Toast.LENGTH_SHORT).show(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,35 @@ | ||||
| package cc.winboll.studio.contacts; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@AliYun.Com | ||||
|  * @Date 2025/02/20 21:14:52 | ||||
|  * @Describe PhoneCallManager | ||||
|  */ | ||||
|  | ||||
| import android.telecom.Call; | ||||
| import android.telecom.VideoProfile; | ||||
|  | ||||
| public class PhoneCallManager { | ||||
|      | ||||
|     public static final String TAG = "PhoneCallManager"; | ||||
|      | ||||
|     public static Call call; | ||||
|  | ||||
|     /** | ||||
|      * 接听电话 | ||||
|      */ | ||||
|     public void answer() { | ||||
|         if (call != null) { | ||||
|             call.answer(VideoProfile.STATE_AUDIO_ONLY); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 断开电话,包括来电时的拒接以及接听后的挂断 | ||||
|      */ | ||||
|     public void disconnect() { | ||||
|         if (call != null) { | ||||
|             call.disconnect(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,40 @@ | ||||
| package cc.winboll.studio.contacts.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@AliYun.Com | ||||
|  * @Date 2025/02/20 20:18:26 | ||||
|  */ | ||||
| import android.content.Intent; | ||||
| import android.net.Uri; | ||||
| import android.os.Bundle; | ||||
| import android.view.View; | ||||
| import android.widget.Button; | ||||
| import android.widget.EditText; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import cc.winboll.studio.contacts.R; | ||||
|  | ||||
| public class DialerActivity extends AppCompatActivity { | ||||
|  | ||||
|     public static final String TAG = "DialerActivity"; | ||||
|  | ||||
|     private EditText phoneNumberEditText; | ||||
|  | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_dialer); | ||||
|  | ||||
|         phoneNumberEditText = findViewById(R.id.phone_number_edit_text); | ||||
|         Button dialButton = findViewById(R.id.dial_button); | ||||
|  | ||||
|         dialButton.setOnClickListener(new View.OnClickListener() { | ||||
|                 @Override | ||||
|                 public void onClick(View v) { | ||||
|                     String phoneNumber = phoneNumberEditText.getText().toString(); | ||||
|                     Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)); | ||||
|                     startActivity(intent); | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -0,0 +1,138 @@ | ||||
| package cc.winboll.studio.contacts.activities; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@AliYun.Com | ||||
|  * @Date 2025/02/21 05:37:42 | ||||
|  */ | ||||
| import android.content.Context; | ||||
| import android.content.DialogInterface; | ||||
| import android.content.Intent; | ||||
| import android.net.Uri; | ||||
| import android.os.Build; | ||||
| import android.os.Bundle; | ||||
| import android.provider.Settings; | ||||
| import android.view.View; | ||||
| import android.view.WindowManager; | ||||
| import android.widget.Toast; | ||||
| import androidx.appcompat.app.AlertDialog; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
| import cc.winboll.studio.contacts.R; | ||||
| import com.hjq.toast.ToastUtils; | ||||
| import java.lang.reflect.Field; | ||||
| import androidx.appcompat.widget.Toolbar; | ||||
| import cc.winboll.studio.libappbase.IWinBollActivity; | ||||
| import cc.winboll.studio.libappbase.bean.APPInfo; | ||||
|  | ||||
| public class SettingsActivity extends AppCompatActivity implements IWinBollActivity { | ||||
|  | ||||
|     public static final String TAG = "SettingsActivity"; | ||||
|  | ||||
|     Toolbar mToolbar; | ||||
|  | ||||
|     @Override | ||||
|     public APPInfo getAppInfo() { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public AppCompatActivity getActivity() { | ||||
|         return this; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String getTag() { | ||||
|         return TAG; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Toolbar initToolBar() { | ||||
|         return findViewById(R.id.activitymainToolbar1); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean isAddWinBollToolBar() { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean isEnableDisplayHomeAsUp() { | ||||
|         return false; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_settings); | ||||
|  | ||||
|         // 初始化工具栏 | ||||
|         mToolbar = findViewById(R.id.activitymainToolbar1); | ||||
|         setSupportActionBar(mToolbar); | ||||
|         if (isEnableDisplayHomeAsUp()) { | ||||
|             // 显示后退按钮 | ||||
|             getSupportActionBar().setDisplayHomeAsUpEnabled(true); | ||||
|         } | ||||
|         getSupportActionBar().setSubtitle(getTag()); | ||||
|          | ||||
|     } | ||||
|  | ||||
|     public void onDefaultPhone(View view) { | ||||
|         Intent intent = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS); | ||||
|         startActivity(intent); | ||||
|     } | ||||
|     public void onCanDrawOverlays(View view) { | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M | ||||
|             && !Settings.canDrawOverlays(this)) { | ||||
|             // 请求 悬浮框 权限 | ||||
|             askForDrawOverlay(); | ||||
|         } else { | ||||
|             ToastUtils.show("悬浮窗已开启"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void askForDrawOverlay() { | ||||
|         AlertDialog alertDialog = new AlertDialog.Builder(this) | ||||
|             .setTitle("允许显示悬浮框") | ||||
|             .setMessage("为了使电话监听服务正常工作,请允许这项权限") | ||||
|             .setPositiveButton("去设置", new DialogInterface.OnClickListener(){ | ||||
|                 @Override | ||||
|                 public void onClick(DialogInterface dialog, int which) { | ||||
|                     openDrawOverlaySettings(); | ||||
|                     dialog.dismiss(); | ||||
|                 } | ||||
|             }) | ||||
|             .setNegativeButton("稍后再说", new DialogInterface.OnClickListener(){ | ||||
|                 @Override | ||||
|                 public void onClick(DialogInterface dialog, int which) { | ||||
|                     dialog.dismiss(); | ||||
|                 } | ||||
|             }) | ||||
|             .create(); | ||||
|  | ||||
|         //noinspection ConstantConditions | ||||
|         alertDialog.getWindow().setFlags( | ||||
|             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, | ||||
|             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); | ||||
|         alertDialog.show(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 跳转悬浮窗管理设置界面 | ||||
|      */ | ||||
|     private void openDrawOverlaySettings() { | ||||
|         if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||||
|             // Android M 以上引导用户去系统设置中打开允许悬浮窗 | ||||
|             // 使用反射是为了用尽可能少的代码保证在大部分机型上都可用 | ||||
|             try { | ||||
|                 Context context = this; | ||||
|                 Class clazz = Settings.class; | ||||
|                 Field field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION"); | ||||
|                 Intent intent = new Intent(field.get(null).toString()); | ||||
|                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
|                 intent.setData(Uri.parse("package:" + context.getPackageName())); | ||||
|                 context.startActivity(intent); | ||||
|             } catch (Exception e) { | ||||
|                 Toast.makeText(this, "请在悬浮窗管理中打开权限", Toast.LENGTH_LONG).show(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,206 @@ | ||||
| package cc.winboll.studio.contacts.listenphonecall; | ||||
|  | ||||
| import android.app.Service; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.content.pm.ActivityInfo; | ||||
| import android.graphics.PixelFormat; | ||||
| import android.os.Build; | ||||
| import android.os.IBinder; | ||||
| import android.telephony.PhoneStateListener; | ||||
| import android.telephony.TelephonyManager; | ||||
| import android.text.TextUtils; | ||||
| import android.view.Gravity; | ||||
| import android.view.KeyEvent; | ||||
| import android.view.LayoutInflater; | ||||
| import android.view.View; | ||||
| import android.view.WindowManager; | ||||
| import android.widget.Button; | ||||
| import android.widget.FrameLayout; | ||||
| import android.widget.TextView; | ||||
| import androidx.annotation.Nullable; | ||||
| import cc.winboll.studio.contacts.MainActivity; | ||||
| import cc.winboll.studio.contacts.R; | ||||
|  | ||||
|  | ||||
| public class CallListenerService extends Service { | ||||
|  | ||||
|     private View phoneCallView; | ||||
|     private TextView tvCallNumber; | ||||
|     private Button btnOpenApp; | ||||
|  | ||||
|     private WindowManager windowManager; | ||||
|     private WindowManager.LayoutParams params; | ||||
|  | ||||
|     private PhoneStateListener phoneStateListener; | ||||
|     private TelephonyManager telephonyManager; | ||||
|  | ||||
|     private String callNumber; | ||||
|     private boolean hasShown; | ||||
|     private boolean isCallingIn; | ||||
|  | ||||
|     @Override | ||||
|     public void onCreate() { | ||||
|         super.onCreate(); | ||||
|  | ||||
|         initPhoneStateListener(); | ||||
|  | ||||
|         initPhoneCallView(); | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     @Override | ||||
|     public IBinder onBind(Intent intent) { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 初始化来电状态监听器 | ||||
|      */ | ||||
|     private void initPhoneStateListener() { | ||||
|         phoneStateListener = new PhoneStateListener() { | ||||
|             @Override | ||||
|             public void onCallStateChanged(int state, String incomingNumber) { | ||||
|                 super.onCallStateChanged(state, incomingNumber); | ||||
|  | ||||
|                 callNumber = incomingNumber; | ||||
|  | ||||
|                 switch (state) { | ||||
|                     case TelephonyManager.CALL_STATE_IDLE: // 待机,即无电话时,挂断时触发 | ||||
|                         dismiss(); | ||||
|                         break; | ||||
|  | ||||
|                     case TelephonyManager.CALL_STATE_RINGING: // 响铃,来电时触发 | ||||
|                         isCallingIn = true; | ||||
|                         updateUI(); | ||||
|                         show(); | ||||
|                         break; | ||||
|  | ||||
|                     case TelephonyManager.CALL_STATE_OFFHOOK: // 摘机,接听或拨出电话时触发 | ||||
|                         updateUI(); | ||||
|                         show(); | ||||
|                         break; | ||||
|  | ||||
|                     default: | ||||
|                         break; | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         // 设置来电监听器 | ||||
|         telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); | ||||
|         if (telephonyManager != null) { | ||||
|             telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     private void initPhoneCallView() { | ||||
|         windowManager = (WindowManager) getApplicationContext() | ||||
|             .getSystemService(Context.WINDOW_SERVICE); | ||||
|         int width = windowManager.getDefaultDisplay().getWidth(); | ||||
|         int height = windowManager.getDefaultDisplay().getHeight(); | ||||
|  | ||||
|         params = new WindowManager.LayoutParams(); | ||||
|         params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; | ||||
|         params.width = width; | ||||
|         params.height = WindowManager.LayoutParams.WRAP_CONTENT; | ||||
|         params.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; | ||||
|  | ||||
|         // 设置图片格式,效果为背景透明 | ||||
|         params.format = PixelFormat.TRANSLUCENT; | ||||
|         // 设置 Window flag 为系统级弹框 | 覆盖表层 | ||||
|         params.type = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ? | ||||
|             WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : | ||||
|             WindowManager.LayoutParams.TYPE_PHONE; | ||||
|  | ||||
|         // 不可聚集(不响应返回键)| 全屏 | ||||
|         params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | ||||
|             | WindowManager.LayoutParams.FLAG_FULLSCREEN | ||||
|             | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; | ||||
|         // API 19 以上则还可以开启透明状态栏与导航栏 | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | ||||
|             params.flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | ||||
|                 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION | ||||
|                 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | ||||
|                 | WindowManager.LayoutParams.FLAG_FULLSCREEN | ||||
|                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; | ||||
|         } | ||||
|  | ||||
|         FrameLayout interceptorLayout = new FrameLayout(this) { | ||||
|  | ||||
|             @Override | ||||
|             public boolean dispatchKeyEvent(KeyEvent event) { | ||||
|  | ||||
|                 if (event.getAction() == KeyEvent.ACTION_DOWN) { | ||||
|                     if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { | ||||
|  | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 return super.dispatchKeyEvent(event); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         phoneCallView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)) | ||||
|             .inflate(R.layout.view_phone_call, interceptorLayout); | ||||
|         tvCallNumber = phoneCallView.findViewById(R.id.tv_call_number); | ||||
|         btnOpenApp = phoneCallView.findViewById(R.id.btn_open_app); | ||||
|         btnOpenApp.setOnClickListener(new View.OnClickListener(){ | ||||
|  | ||||
|                 @Override | ||||
|                 public void onClick(View view) { | ||||
|                     Intent intent = new Intent(getApplicationContext(), MainActivity.class); | ||||
|                     intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
|                     CallListenerService.this.startActivity(intent); | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 显示顶级弹框展示通话信息 | ||||
|      */ | ||||
|     private void show() { | ||||
|         if (!hasShown) { | ||||
|             windowManager.addView(phoneCallView, params); | ||||
|             hasShown = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 取消显示 | ||||
|      */ | ||||
|     private void dismiss() { | ||||
|         if (hasShown) { | ||||
|             windowManager.removeView(phoneCallView); | ||||
|             isCallingIn = false; | ||||
|             hasShown = false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void updateUI() { | ||||
|         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); | ||||
|     } | ||||
|  | ||||
|     public static String formatPhoneNumber(String phoneNum) { | ||||
|         if (!TextUtils.isEmpty(phoneNum) && phoneNum.length() == 11) { | ||||
|             return phoneNum.substring(0, 3) + "-" | ||||
|                 + phoneNum.substring(3, 7) + "-" | ||||
|                 + phoneNum.substring(7); | ||||
|         } | ||||
|         return phoneNum; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|  | ||||
|         telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,166 @@ | ||||
| package cc.winboll.studio.contacts.phonecallui; | ||||
|  | ||||
| import static cc.winboll.studio.contacts.listenphonecall.CallListenerService.formatPhoneNumber; | ||||
|  | ||||
| import android.annotation.SuppressLint; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| import android.os.Build; | ||||
| import android.os.Bundle; | ||||
| import android.view.View; | ||||
| import android.view.WindowManager; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import androidx.annotation.RequiresApi; | ||||
| import androidx.appcompat.app.AppCompatActivity; | ||||
|  | ||||
| import cc.winboll.studio.contacts.ActivityStack; | ||||
| import cc.winboll.studio.contacts.R; | ||||
|  | ||||
| import java.util.Timer; | ||||
| import java.util.TimerTask; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 提供接打电话的界面,仅支持 Android M (6.0, API 23) 及以上的系统 | ||||
|  * | ||||
|  * @author aJIEw | ||||
|  */ | ||||
| @RequiresApi(api = Build.VERSION_CODES.M) | ||||
| public class PhoneCallActivity extends AppCompatActivity implements View.OnClickListener { | ||||
|  | ||||
|     private TextView tvCallNumberLabel; | ||||
|     private TextView tvCallNumber; | ||||
|     private TextView tvPickUp; | ||||
|     private TextView tvCallingTime; | ||||
|     private TextView tvHangUp; | ||||
|  | ||||
|     private PhoneCallManager phoneCallManager; | ||||
|     private PhoneCallService.CallType callType; | ||||
|     private String phoneNumber; | ||||
|  | ||||
|     private Timer onGoingCallTimer; | ||||
|     private int callingTime; | ||||
|  | ||||
|     public static void actionStart(Context context, String phoneNumber, | ||||
|                                    PhoneCallService.CallType callType) { | ||||
|         Intent intent = new Intent(context, PhoneCallActivity.class); | ||||
|         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | ||||
|         intent.putExtra(Intent.EXTRA_MIME_TYPES, callType); | ||||
|         intent.putExtra(Intent.EXTRA_PHONE_NUMBER, phoneNumber); | ||||
|         context.startActivity(intent); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         setContentView(R.layout.activity_phone_call); | ||||
|  | ||||
|         ActivityStack.getInstance().addActivity(this); | ||||
|  | ||||
|         initData(); | ||||
|  | ||||
|         initView(); | ||||
|     } | ||||
|  | ||||
|     private void initData() { | ||||
|         phoneCallManager = new PhoneCallManager(this); | ||||
|         onGoingCallTimer = new Timer(); | ||||
|         if (getIntent() != null) { | ||||
|             phoneNumber = getIntent().getStringExtra(Intent.EXTRA_PHONE_NUMBER); | ||||
|             callType = (PhoneCallService.CallType) getIntent().getSerializableExtra(Intent.EXTRA_MIME_TYPES); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void initView() { | ||||
|         int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | ||||
|                 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION //hide navigationBar | ||||
|                 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | ||||
|                 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; | ||||
|         getWindow().getDecorView().setSystemUiVisibility(uiOptions); | ||||
|         getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); | ||||
|  | ||||
|         tvCallNumberLabel = findViewById(R.id.tv_call_number_label); | ||||
|         tvCallNumber = findViewById(R.id.tv_call_number); | ||||
|         tvPickUp = findViewById(R.id.tv_phone_pick_up); | ||||
|         tvCallingTime = findViewById(R.id.tv_phone_calling_time); | ||||
|         tvHangUp = findViewById(R.id.tv_phone_hang_up); | ||||
|  | ||||
|         tvCallNumber.setText(formatPhoneNumber(phoneNumber)); | ||||
|         tvPickUp.setOnClickListener(this); | ||||
|         tvHangUp.setOnClickListener(this); | ||||
|  | ||||
|         // 打进的电话 | ||||
|         if (callType == PhoneCallService.CallType.CALL_IN) { | ||||
|             tvCallNumberLabel.setText("来电号码"); | ||||
|             tvPickUp.setVisibility(View.VISIBLE); | ||||
|         } | ||||
|         // 打出的电话 | ||||
|         else if (callType == PhoneCallService.CallType.CALL_OUT) { | ||||
|             tvCallNumberLabel.setText("呼叫号码"); | ||||
|             tvPickUp.setVisibility(View.GONE); | ||||
|             phoneCallManager.openSpeaker(); | ||||
|         } | ||||
|  | ||||
|         showOnLockScreen(); | ||||
|     } | ||||
|  | ||||
|     public void showOnLockScreen() { | ||||
|         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | | ||||
|                         WindowManager.LayoutParams.FLAG_FULLSCREEN | | ||||
|                         WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | | ||||
|                         WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON, | ||||
|                 WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | | ||||
|                         WindowManager.LayoutParams.FLAG_FULLSCREEN | | ||||
|                         WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | | ||||
|                         WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onClick(View v) { | ||||
|         if (v.getId() == R.id.tv_phone_pick_up) { | ||||
|             phoneCallManager.answer(); | ||||
|             tvPickUp.setVisibility(View.GONE); | ||||
|             tvCallingTime.setVisibility(View.VISIBLE); | ||||
|             onGoingCallTimer.schedule(new TimerTask() { | ||||
|                 @Override | ||||
|                 public void run() { | ||||
|                     runOnUiThread(new Runnable() { | ||||
|                         @SuppressLint("SetTextI18n") | ||||
|                         @Override | ||||
|                         public void run() { | ||||
|                             callingTime++; | ||||
|                             tvCallingTime.setText("通话中:" + getCallingTime()); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             }, 0, 1000); | ||||
|         } else if (v.getId() == R.id.tv_phone_hang_up) { | ||||
|             phoneCallManager.disconnect(); | ||||
|             stopTimer(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private String getCallingTime() { | ||||
|         int minute = callingTime / 60; | ||||
|         int second = callingTime % 60; | ||||
|         return (minute < 10 ? "0" + minute : minute) + | ||||
|                 ":" + | ||||
|                 (second < 10 ? "0" + second : second); | ||||
|     } | ||||
|  | ||||
|     private void stopTimer() { | ||||
|         if (onGoingCallTimer != null) { | ||||
|             onGoingCallTimer.cancel(); | ||||
|         } | ||||
|  | ||||
|         callingTime = 0; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onDestroy() { | ||||
|         super.onDestroy(); | ||||
|  | ||||
|         phoneCallManager.destroy(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,63 @@ | ||||
| package cc.winboll.studio.contacts.phonecallui; | ||||
|  | ||||
| import android.content.Context; | ||||
| import android.media.AudioManager; | ||||
| import android.os.Build; | ||||
| import android.telecom.Call; | ||||
| import android.telecom.VideoProfile; | ||||
|  | ||||
| import androidx.annotation.RequiresApi; | ||||
|  | ||||
|  | ||||
| @RequiresApi(api = Build.VERSION_CODES.M) | ||||
| public class PhoneCallManager { | ||||
|  | ||||
|     public static Call call; | ||||
|  | ||||
|     private Context context; | ||||
|     private AudioManager audioManager; | ||||
|  | ||||
|     public PhoneCallManager(Context context) { | ||||
|         this.context = context; | ||||
|  | ||||
|         audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 接听电话 | ||||
|      */ | ||||
|     public void answer() { | ||||
|         if (call != null) { | ||||
|             call.answer(VideoProfile.STATE_AUDIO_ONLY); | ||||
|             openSpeaker(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 断开电话,包括来电时的拒接以及接听后的挂断 | ||||
|      */ | ||||
|     public void disconnect() { | ||||
|         if (call != null) { | ||||
|             call.disconnect(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 打开免提 | ||||
|      */ | ||||
|     public void openSpeaker() { | ||||
|         if (audioManager != null) { | ||||
|             audioManager.setMode(AudioManager.MODE_IN_CALL); | ||||
|             audioManager.setSpeakerphoneOn(true); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 销毁资源 | ||||
|      */ | ||||
|     public void destroy() { | ||||
|         call = null; | ||||
|         context = null; | ||||
|         audioManager = null; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,76 @@ | ||||
| package cc.winboll.studio.contacts.phonecallui; | ||||
|  | ||||
| import android.os.Build; | ||||
| import android.telecom.Call; | ||||
| import android.telecom.InCallService; | ||||
|  | ||||
| import androidx.annotation.RequiresApi; | ||||
|  | ||||
| import cc.winboll.studio.contacts.ActivityStack; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 监听电话通信状态的服务,实现该类的同时必须提供电话管理的 UI | ||||
|  * | ||||
|  * @author aJIEw | ||||
|  * @see PhoneCallActivity | ||||
|  * @see android.telecom.InCallService | ||||
|  */ | ||||
| @RequiresApi(api = Build.VERSION_CODES.M) | ||||
| public class PhoneCallService extends InCallService { | ||||
|  | ||||
|     private final Call.Callback callback = new Call.Callback() { | ||||
|         @Override | ||||
|         public void onStateChanged(Call call, int state) { | ||||
|             super.onStateChanged(call, state); | ||||
|  | ||||
|             switch (state) { | ||||
|                 case Call.STATE_ACTIVE: { | ||||
|  | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|                 case Call.STATE_DISCONNECTED: { | ||||
|                     ActivityStack.getInstance().finishActivity(PhoneCallActivity.class); | ||||
|                     break; | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     @Override | ||||
|     public void onCallAdded(Call call) { | ||||
|         super.onCallAdded(call); | ||||
|  | ||||
|         call.registerCallback(callback); | ||||
|         PhoneCallManager.call = call; | ||||
|  | ||||
|         CallType callType = null; | ||||
|  | ||||
|         if (call.getState() == Call.STATE_RINGING) { | ||||
|             callType = CallType.CALL_IN; | ||||
|         } else if (call.getState() == Call.STATE_CONNECTING) { | ||||
|             callType = CallType.CALL_OUT; | ||||
|         } | ||||
|  | ||||
|         if (callType != null) { | ||||
|             Call.Details details = call.getDetails(); | ||||
|             String phoneNumber = details.getHandle().getSchemeSpecificPart(); | ||||
|             PhoneCallActivity.actionStart(this, phoneNumber, callType); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onCallRemoved(Call call) { | ||||
|         super.onCallRemoved(call); | ||||
|  | ||||
|         call.unregisterCallback(callback); | ||||
|         PhoneCallManager.call = null; | ||||
|     } | ||||
|  | ||||
|     public enum CallType { | ||||
|         CALL_IN, | ||||
|         CALL_OUT, | ||||
|     } | ||||
| } | ||||
| @@ -32,8 +32,9 @@ public class MainReceiver extends BroadcastReceiver { | ||||
|         String szAction = intent.getAction(); | ||||
|         if (szAction.equals(ACTION_BOOT_COMPLETED)) { | ||||
|             ToastUtils.show("ACTION_BOOT_COMPLETED"); | ||||
|             MainService.startMainService(context); | ||||
|         } else { | ||||
|             ToastUtils.show("szAction"); | ||||
|             ToastUtils.show(szAction); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -42,7 +43,7 @@ public class MainReceiver extends BroadcastReceiver { | ||||
|     public void registerAction(Context context) { | ||||
|         IntentFilter filter=new IntentFilter(); | ||||
|         filter.addAction(ACTION_BOOT_COMPLETED); | ||||
|         filter.addAction(Intent.ACTION_BATTERY_CHANGED); | ||||
|         //filter.addAction(Intent.ACTION_BATTERY_CHANGED); | ||||
|         context.registerReceiver(this, filter); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,34 @@ | ||||
| package cc.winboll.studio.contacts.receivers; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@AliYun.Com | ||||
|  * @Date 2025/02/20 17:54:55 | ||||
|  * @Describe PhoneCallReceiver | ||||
|  */ | ||||
| //import android.content.BroadcastReceiver; | ||||
| //import android.content.Context; | ||||
| //import android.content.Intent; | ||||
| //import android.telephony.TelephonyManager; | ||||
| //import android.util.Log; | ||||
| //import cc.winboll.studio.contacts.services.PhoneCallService; | ||||
| // | ||||
| //public class PhoneReceiver extends BroadcastReceiver { | ||||
| // | ||||
| //    public static final String TAG = "PhoneReceiver"; | ||||
| // | ||||
| //    @Override | ||||
| //    public void onReceive(Context context, Intent intent) { | ||||
| //        if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { | ||||
| //            String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); | ||||
| //            if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { | ||||
| //                String phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); | ||||
| //                Log.d(TAG, "Incoming call from: " + phoneNumber); | ||||
| // | ||||
| //                // 启动服务来处理电话接听 | ||||
| //                Intent serviceIntent = new Intent(context, PhoneCallService.class); | ||||
| //                serviceIntent.putExtra("phoneNumber", phoneNumber); | ||||
| //                context.startService(serviceIntent); | ||||
| //            } | ||||
| //        } | ||||
| //    } | ||||
| //} | ||||
| @@ -11,6 +11,7 @@ package cc.winboll.studio.contacts.services; | ||||
|  * https://blog.csdn.net/cyp331203/article/details/38920491 | ||||
|  */ | ||||
| import android.app.Service; | ||||
| import cc.winboll.studio.contacts.listenphonecall.CallListenerService; | ||||
| import android.content.ComponentName; | ||||
| import android.content.Context; | ||||
| import android.content.Intent; | ||||
| @@ -97,7 +98,8 @@ public class MainService extends Service { | ||||
|                 mMainReceiver = new MainReceiver(this); | ||||
|                 mMainReceiver.registerAction(this); | ||||
|             } | ||||
|  | ||||
|              | ||||
|             startPhoneCallListener(); | ||||
|  | ||||
|             MainServiceThread.getInstance(this, mMainServiceHandler).start(); | ||||
|  | ||||
| @@ -125,6 +127,11 @@ public class MainService extends Service { | ||||
| //        LogUtils.d(TAG, "startService(intent)"); | ||||
| //        bindService(new Intent(this, AssistantService.class), mMyServiceConnection, Context.BIND_IMPORTANT); | ||||
|     } | ||||
|      | ||||
|     void startPhoneCallListener() { | ||||
|         Intent callListener = new Intent(this, CallListenerService.class); | ||||
|         startService(callListener); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onDestroy() { | ||||
|   | ||||
| @@ -0,0 +1,75 @@ | ||||
| package cc.winboll.studio.contacts.services; | ||||
|  | ||||
| /** | ||||
|  * @Author ZhanGSKen@AliYun.Com | ||||
|  * @Date 2025/02/20 19:58:02 | ||||
|  * @Describe MyPhoneCallService | ||||
|  */ | ||||
| import android.telecom.Call; | ||||
| import android.telecom.InCallService; | ||||
| import cc.winboll.studio.contacts.PhoneCallManager; | ||||
|  | ||||
| public class PhoneCallService extends InCallService { | ||||
|  | ||||
|     public static final String TAG = "PhoneCallService"; | ||||
|  | ||||
|     private Call.Callback callback = new Call.Callback() { | ||||
|         @Override | ||||
|         public void onStateChanged(Call call, int state) { | ||||
|             super.onStateChanged(call, state); | ||||
|             switch (state) { | ||||
|                 case Call.STATE_ACTIVE: { | ||||
|                         break; // 通话中 | ||||
|                     } | ||||
|                 case Call.STATE_DISCONNECTED: { | ||||
|                         break; // 通话结束 | ||||
|                     } | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| //    @Override | ||||
| //    public void onCallAdded(Call call) { | ||||
| //        super.onCallAdded(call); | ||||
| // | ||||
| //        call.registerCallback(callback); | ||||
| //    } | ||||
| // | ||||
| //    @Override | ||||
| //    public void onCallRemoved(Call call) { | ||||
| //        super.onCallRemoved(call); | ||||
| // | ||||
| //        call.unregisterCallback(callback); | ||||
| //    } | ||||
|      | ||||
|     @Override | ||||
|     public void onCallAdded(Call call) { | ||||
|         super.onCallAdded(call); | ||||
|  | ||||
|         call.registerCallback(callback); | ||||
|         PhoneCallManager.call = call; // 传入call | ||||
|  | ||||
| //        CallType callType = null; | ||||
| // | ||||
| //        if (call.getState() == Call.STATE_RINGING) { | ||||
| //            callType = CallType.CALL_IN; | ||||
| //        } else if (call.getState() == Call.STATE_CONNECTING) { | ||||
| //            callType = CallType.CALL_OUT; | ||||
| //        } | ||||
| // | ||||
| //        if (callType != null) { | ||||
| //            Call.Details details = call.getDetails(); | ||||
| //            String phoneNumber = details.getHandle().toString().substring(4) | ||||
| //                .replaceAll("%20", ""); // 去除拨出电话中的空格 | ||||
| //            PhoneCallActivity.actionStart(this, phoneNumber, callType); | ||||
| //        } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onCallRemoved(Call call) { | ||||
|         super.onCallRemoved(call); | ||||
|  | ||||
|         call.unregisterCallback(callback); | ||||
|         PhoneCallManager.call = null; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								contacts/src/main/res/drawable/ic_phone_call_in.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								contacts/src/main/res/drawable/ic_phone_call_in.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="36dp" | ||||
|     android:height="36dp" | ||||
|     android:viewportHeight="1024" | ||||
|     android:viewportWidth="1024"> | ||||
|     <path | ||||
|         android:fillColor="#fff" | ||||
|         android:pathData="M847.53,307.03L597.5,307.03c-8.54,0.17 -13.66,-11.26 -13.66,-19.97 0.17,-8.7 5.12,-14.17 13.66,-14.17h250.02c30.21,-0.34 31.41,34.14 0,34.14zM736.6,428.71c-6.14,6.32 -16.05,6.32 -22.02,0.17l-128.34,-130.56c-5.98,-6.14 -5.8,-16.22 0.17,-22.53l122.37,-124.76c6.14,-6.31 16.05,-6.31 22.02,-0.34 5.98,6.14 5.81,16.22 -0.34,22.36L623.1,289.62l113.5,116.22a16.33,16.33 0,0 1,0 22.87zM833.02,717.99c-18.78,-12.63 -122.37,-64.85 -141.99,-77.14 -2.05,0 -7.34,0.68 -14.85,4.43 -8.02,4.1 -31.23,16.9 -63.66,34.99l-25.26,14.16 -23.9,-16.38c-17.75,-12.11 -56.32,-41.3 -115.03,-98.64 -58.88,-57.69 -88.58,-95.23 -101.04,-112.47l-16.72,-23.38L345.09,418.82c13.99,-23.9 30.72,-52.9 35.84,-62.46 4.1,-7.51 4.44,-12.63 4.44,-14.17v-0.51C374.27,324.44 303.27,219.65 290.3,201.22c-1.88,-0.34 -5.8,0 -10.75,3.42 -40.28,28.5 -82.43,68.95 -88.41,84.65C195.24,373.42 270.85,491.52 404.48,622.25c133.8,130.73 251.22,205.49 336.9,209.41 16.22,-5.63 62.81,-52.05 91.65,-91.14 2.05,-2.9 3.24,-3.58 3.24,-6.99 0,-0.51 -3.07,-15.02 -3.24,-15.53zM867.5,770.73c-0.68,1.02 -81.58,108.03 -126.12,106.67 -125.1,-3.93 -265.73,-128.86 -366.94,-227.84 -101.38,-98.99 -225.45,-238.25 -229.38,-360.96v-1.02c0,-43.01 124.76,-128 125.78,-128.69 19.62,-13.14 36.35,-13.82 52.39,10.41 7.85,10.92 87.73,123.9 96.94,138.58 3.92,6.49 11.09,25.94 11.09,34.48 0,10.92 -3.24,23.21 -9.73,34.98 -6.31,11.61 -26.62,46.59 -36.69,63.83 10.92,15.19 46.76,61.44 103.94,117.25 56.83,55.63 85.16,72.19 100.69,82.77 17.58,-9.73 53.42,-29.7 65.2,-35.67 22.18,-11.44 44.37,-12.8 59.39,-3.42 14.16,8.7 136.02,88.41 147.79,96.6 10.93,7.68 16.9,21.67 16.9,36.69 0.17,11.78 -3.58,24.41 -11.26,35.33z" /> | ||||
| </vector> | ||||
							
								
								
									
										9
									
								
								contacts/src/main/res/drawable/ic_phone_call_out.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								contacts/src/main/res/drawable/ic_phone_call_out.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="36dp" | ||||
|     android:height="36dp" | ||||
|     android:viewportHeight="1024" | ||||
|     android:viewportWidth="1024"> | ||||
|     <path | ||||
|         android:fillColor="#fff" | ||||
|         android:pathData="M861.86,307.03L614.4,307.03c-31.06,-0.17 -29.86,-34.48 0,-34.14h247.46c8.54,0.17 13.31,5.46 13.49,14.17 0,8.87 -4.95,20.14 -13.49,19.97zM872.96,298.5l-126.98,130.56c-5.98,6.14 -15.7,5.98 -21.85,-0.17 -6.14,-6.32 -6.14,-16.38 -0.17,-22.36l112.3,-116.22L730.11,173.74c-6.14,-6.31 -6.14,-16.38 -0.17,-22.35 5.97,-6.14 15.7,-5.98 21.84,0.34L872.96,276.48c5.8,5.8 5.98,15.87 0,22.02zM833.02,717.99c-18.78,-12.63 -122.37,-64.85 -141.99,-77.14 -2.05,0 -7.34,0.68 -14.85,4.43 -8.02,4.1 -31.23,16.9 -63.66,34.99l-25.26,14.16 -23.9,-16.38c-17.75,-12.11 -56.32,-41.3 -115.03,-98.64 -58.88,-57.69 -88.41,-95.23 -100.86,-112.47L330.75,443.56l14.5,-24.74c14,-23.9 30.72,-52.9 35.84,-62.46 4.1,-7.51 4.44,-12.63 4.44,-14.17v-0.51C374.44,324.44 303.45,219.65 290.3,201.22c-1.88,-0.34 -5.8,0 -10.75,3.42 -40.28,28.5 -82.43,68.95 -88.41,84.65C195.24,373.42 270.85,491.52 404.48,622.25c133.63,130.73 251.05,205.49 336.9,209.41 16.22,-5.63 62.81,-52.05 91.65,-91.14 2.05,-2.9 3.24,-3.58 3.24,-6.99 0,-0.51 -3.07,-15.02 -3.24,-15.53zM867.5,770.73c-0.68,1.02 -81.58,108.03 -126.12,106.67 -125.1,-3.93 -265.56,-128.86 -366.94,-227.84 -101.38,-98.99 -225.45,-238.25 -229.38,-360.96v-1.02c0,-43.01 124.76,-128 125.78,-128.69 19.62,-13.14 36.35,-13.82 52.39,10.41 7.85,10.92 87.73,123.9 96.94,138.58 4.1,6.49 11.09,25.94 11.09,34.48 0,10.92 -3.24,23.21 -9.73,34.98 -6.14,11.61 -26.62,46.59 -36.69,63.83 10.75,15.19 46.76,61.44 103.94,117.25 56.83,55.63 85.16,72.19 100.69,82.77 17.58,-9.73 53.42,-29.7 65.2,-35.67 22.18,-11.44 44.37,-12.8 59.39,-3.42 14.16,8.7 136.19,88.41 147.79,96.6 10.93,7.68 16.9,21.67 16.9,36.69 0.17,11.78 -3.58,24.41 -11.26,35.33z" /> | ||||
| </vector> | ||||
							
								
								
									
										9
									
								
								contacts/src/main/res/drawable/ic_phone_hang_up.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								contacts/src/main/res/drawable/ic_phone_hang_up.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="64dp" | ||||
|     android:height="64dp" | ||||
|     android:viewportHeight="1024" | ||||
|     android:viewportWidth="1024"> | ||||
|     <path | ||||
|         android:fillColor="#201f1f" | ||||
|         android:pathData="M841.22,856.06c185.86,-185.86 185.86,-487.42 0,-673.79C655.36,-3.58 353.79,-3.58 167.42,182.27c-185.86,185.86 -185.86,487.42 0,673.79 186.37,185.86 487.94,185.86 673.79,0zM218.62,495.1c0,-47.62 111.1,-113.66 285.7,-113.66 175.1,0 285.7,66.05 285.7,113.66 0,40.96 10.75,102.4 -73.73,93.18 -84.48,-9.22 -78.85,-40.96 -78.85,-83.46 0,-29.7 -68.61,-36.35 -133.12,-36.35 -65.02,0 -133.12,6.66 -133.12,36.35 0,42.5 5.63,74.24 -78.85,83.46 -84.99,9.22 -73.73,-51.71 -73.73,-93.18z" /> | ||||
| </vector> | ||||
							
								
								
									
										30
									
								
								contacts/src/main/res/drawable/ic_phone_pick_up.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								contacts/src/main/res/drawable/ic_phone_pick_up.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="64dp" | ||||
|     android:height="64dp" | ||||
|     android:viewportHeight="1024" | ||||
|     android:viewportWidth="1024"> | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         android:pathData="M277.9,742s167.9,-294.1 465.3,-465.3C575.7,577.8 277.9,742 277.9,742z" /> | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         android:pathData="M743.1,742S575.2,447.9 277.8,276.7C445.3,577.8 743.1,742 743.1,742z" /> | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         android:pathData="M284.1,343m-49,0a49,49 0,1 0,98 0,49 49,0 1,0 -98,0Z" /> | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         android:pathData="M284.1,515.5m-49,0a49,49 0,1 0,98 0,49 49,0 1,0 -98,0Z" /> | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         android:pathData="M284.1,683.5m-49,0a49,49 0,1 0,98 0,49 49,0 1,0 -98,0Z" /> | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         android:pathData="M808.4,341.6s-208.5,-61.2 -420,0c211.5,64.8 420,0 420,0zM808.4,516.6s-208.5,-61.2 -420,0c211.5,64.8 420,0 420,0zM808.4,684.6s-208.5,-61.2 -420,0c211.5,64.8 420,0 420,0z" /> | ||||
|     <path | ||||
|         android:fillColor="#0EC469" | ||||
|         android:pathData="M512,512m-448,0a448,448 0,1 0,896 0,448 448,0 1,0 -896,0Z" /> | ||||
|     <path | ||||
|         android:fillColor="#FFFFFF" | ||||
|         android:pathData="M701.4,786.8h-0.3c-3.2,-0.3 -6.4,-0.8 -9.5,-1.4C290,725.2 237.2,331.5 237.2,331.5h0.1c-5.9,-27.8 0.8,-56.8 22.5,-78.5 9.5,-9.5 22.5,-18.1 31.3,-19.2l111.6,111.6c-1.1,8.8 -9.6,21.7 -19.1,31.2 -8.5,8.5 -17.9,14.4 -28.4,18.6 57.7,214.5 272.1,271.5 272.1,271.5l0.3,0.2c4.2,-10.5 9.6,-19.3 18.1,-27.8 9.5,-9.5 22.6,-18.1 31.4,-19.2l111.6,111.6c-1.1,8.8 -9.6,21.7 -19.1,31.2 -18.9,19 -43.4,26.3 -68.2,24.1z" /> | ||||
| </vector> | ||||
							
								
								
									
										22
									
								
								contacts/src/main/res/layout/activity_dialer.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								contacts/src/main/res/layout/activity_dialer.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:orientation="vertical" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:padding="16dp"> | ||||
|  | ||||
|     <EditText | ||||
|         android:id="@+id/phone_number_edit_text" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:hint="Enter phone number" /> | ||||
|  | ||||
|     <Button | ||||
|         android:id="@+id/dial_button" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="Dial" /> | ||||
|  | ||||
| </LinearLayout> | ||||
							
								
								
									
										95
									
								
								contacts/src/main/res/layout/activity_phone_call.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								contacts/src/main/res/layout/activity_phone_call.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:orientation="vertical" | ||||
|     tools:context=".phonecallui.PhoneCallActivity"> | ||||
|  | ||||
|     <RelativeLayout | ||||
|         android:id="@+id/rl_user_info" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="300dp" | ||||
|         android:background="@color/colorPrimaryDark"> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/tv_call_number_label" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_above="@+id/tv_call_number" | ||||
|             android:layout_marginBottom="16dp" | ||||
|             android:gravity="center" | ||||
|             android:text="来电号码" | ||||
|             android:textColor="@android:color/white" | ||||
|             android:textSize="18sp" /> | ||||
|  | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/tv_call_number" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:gravity="center" | ||||
|             android:textAlignment="center" | ||||
|             android:textColor="@android:color/white" | ||||
|             android:textSize="28sp" | ||||
|             android:textStyle="bold" | ||||
|             android:layout_centerInParent="true" | ||||
|             tools:text="133-9527-9527" /> | ||||
|  | ||||
|     </RelativeLayout> | ||||
|  | ||||
|     <RelativeLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:background="@android:color/white"> | ||||
|  | ||||
|         <TextView | ||||
|             android:id="@+id/tv_phone_calling_time" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_centerHorizontal="true" | ||||
|             android:layout_marginTop="24dp" | ||||
|             android:text="通话中:01:33" | ||||
|             android:textColor="@android:color/black" | ||||
|             android:textSize="18sp" | ||||
|             android:visibility="gone" | ||||
|             tools:visibility="visible" /> | ||||
|  | ||||
|         <RelativeLayout | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:layout_centerInParent="true"> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/tv_phone_hang_up" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:drawablePadding="16dp" | ||||
|                 android:drawableTop="@drawable/ic_phone_hang_up" | ||||
|                 android:foreground="?android:attr/selectableItemBackground" | ||||
|                 android:gravity="center" | ||||
|                 android:padding="8dp" | ||||
|                 android:text="挂  断" | ||||
|                 android:textColor="@android:color/black" | ||||
|                 tools:visibility="visible" /> | ||||
|  | ||||
|             <TextView | ||||
|                 android:id="@+id/tv_phone_pick_up" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_marginLeft="50dp" | ||||
|                 android:layout_toRightOf="@id/tv_phone_hang_up" | ||||
|                 android:drawablePadding="16dp" | ||||
|                 android:drawableTop="@drawable/ic_phone_pick_up" | ||||
|                 android:foreground="?android:attr/selectableItemBackground" | ||||
|                 android:gravity="center" | ||||
|                 android:padding="8dp" | ||||
|                 android:text="接  听" | ||||
|                 android:textColor="@android:color/black" | ||||
|                 android:visibility="gone" | ||||
|                 tools:visibility="visible" /> | ||||
|         </RelativeLayout> | ||||
|  | ||||
|     </RelativeLayout> | ||||
| </LinearLayout> | ||||
							
								
								
									
										46
									
								
								contacts/src/main/res/layout/activity_settings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								contacts/src/main/res/layout/activity_settings.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout | ||||
| 	xmlns:android="http://schemas.android.com/apk/res/android" | ||||
| 	xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
| 	xmlns:tools="http://schemas.android.com/tools" | ||||
| 	android:orientation="vertical" | ||||
| 	android:layout_width="match_parent" | ||||
| 	android:layout_height="match_parent"> | ||||
|  | ||||
| 	<androidx.appcompat.widget.Toolbar | ||||
| 		android:layout_width="match_parent" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:id="@+id/activitymainToolbar1"/> | ||||
|  | ||||
| 	<LinearLayout | ||||
| 		android:orientation="vertical" | ||||
| 		android:layout_width="match_parent" | ||||
| 		android:layout_height="0dp" | ||||
| 		android:layout_weight="1.0"> | ||||
|  | ||||
| 		<LinearLayout | ||||
| 			android:orientation="horizontal" | ||||
| 			android:layout_width="match_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:gravity="right"> | ||||
|  | ||||
| 			<Button | ||||
| 				android:layout_width="wrap_content" | ||||
| 				android:layout_height="wrap_content" | ||||
| 				android:text="悬浮窗设置" | ||||
| 				android:id="@+id/activitysettingsButton2" | ||||
| 				android:onClick="onCanDrawOverlays"/> | ||||
|  | ||||
| 			<Button | ||||
| 				android:layout_width="wrap_content" | ||||
| 				android:layout_height="wrap_content" | ||||
| 				android:text="默认拨号设置" | ||||
| 				android:id="@+id/activitysettingsButton1" | ||||
| 				android:onClick="onDefaultPhone"/> | ||||
|  | ||||
| 		</LinearLayout> | ||||
|  | ||||
| 	</LinearLayout> | ||||
|  | ||||
| </LinearLayout> | ||||
|  | ||||
							
								
								
									
										33
									
								
								contacts/src/main/res/layout/view_phone_call.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								contacts/src/main/res/layout/view_phone_call.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:id="@+id/rl_user_info" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:background="@color/colorPrimary"> | ||||
|  | ||||
|     <TextView | ||||
|         android:id="@+id/tv_call_number" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_centerHorizontal="true" | ||||
|         android:layout_marginTop="30dp" | ||||
|         android:gravity="center" | ||||
|         android:textAlignment="center" | ||||
|         android:textColor="@android:color/white" | ||||
|         android:textSize="18sp" | ||||
|         tools:text="133-8892-9579" /> | ||||
|  | ||||
|     <Button | ||||
|         android:id="@+id/btn_open_app" | ||||
|         style="@style/Base.Widget.AppCompat.Button.Borderless.Colored" | ||||
|         android:layout_width="match_parent" | ||||
|         android:textColor="@android:color/white" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_below="@id/tv_call_number" | ||||
|         android:gravity="center" | ||||
|         android:text="打开 Phone Call App" | ||||
|         android:textAlignment="center" | ||||
|         android:textSize="16sp" /> | ||||
|  | ||||
| </RelativeLayout> | ||||
| @@ -5,5 +5,8 @@ | ||||
|     <item | ||||
|         android:id="@+id/item_call" | ||||
|         android:title="CallActivity"/> | ||||
|      | ||||
|  | ||||
|     <item | ||||
|         android:id="@+id/item_settings" | ||||
|         android:title="SettingsActivity"/> | ||||
| </menu> | ||||
|   | ||||
| @@ -1,6 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <style name="MyAppTheme" parent="APPBaseTheme"> | ||||
|         <item name="colorPrimary">@color/colorPrimary</item> | ||||
|         <item name="colorPrimaryDark">@color/colorPrimaryDark</item> | ||||
|         <item name="colorAccent">@color/colorAccent</item> | ||||
|         <item name="android:windowFullscreen">true</item> | ||||
|         <item name="android:windowContentOverlay">@null</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="GlobalCrashActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar"> | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| #Created by .winboll/winboll_app_build.gradle | ||||
| #Thu Feb 20 09:27:14 GMT 2025 | ||||
| #Thu Feb 20 22:09:07 GMT 2025 | ||||
| stageCount=0 | ||||
| libraryProject=winboll-shared | ||||
| baseVersion=1.0 | ||||
| publishVersion=1.0.0 | ||||
| buildCount=99 | ||||
| buildCount=126 | ||||
| baseBetaVersion=1.0.1 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ZhanGSKen
					ZhanGSKen