如何在 Android 中向用户提示默认短信应用选择器?

问题描述 投票:0回答:3

我创建了一个消息应用程序,可以从设置中将其设为默认值。我的目标是在我的应用程序中提示短信应用程序默认选择器。

android sms default
3个回答
2
投票

我实际上找到了实现目标的方法。对于 android 10,这是通过 RoleManager 类实现的:

RoleManager roleManager;
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
         roleManager = getApplicationContext().getSystemService(RoleManager.class);
         if (roleManager.isRoleAvailable(RoleManager.ROLE_SMS)) {
             if (roleManager.isRoleHeld(RoleManager.ROLE_SMS)) {
                 Toast.makeText(getApplicationContext(), "PrismApp set as default.", Toast.LENGTH_SHORT).show();
                 Intent i = new Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
                 startActivity(i);
             } else {
                 Intent roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS);
                 startActivityForResult(roleRequestIntent, 2);
             }
         }
     }

预期结果: android 10

对于android 10之前的android版本,找到了两种方法,一种简单,一种复杂,但值得。 简单的方法:

String myPackageName = getPackageName();
     Intent setSmsAppIntent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
     setSmsAppIntent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName);
     startActivity(setSmsAppIntent);

预期结果: simple method

第二种方法:

private static  final int DEF_SMS_REQ = 0;
 private AppInfo selectedApp;
 private void selectDefaultSmsPackage() {
     @SuppressLint("QueryPermissionsNeeded") final List<ResolveInfo> receivers = getPackageManager().queryBroadcastReceivers(new
             Intent(Telephony.Sms.Intents.SMS_DELIVER_ACTION), 0);
     final ArrayList<AppInfo> apps = new ArrayList<>();
     for (ResolveInfo info : receivers) {
         final String packageName = info.activityInfo.packageName;
         final String appName = getPackageManager().getApplicationLabel(info.activityInfo.applicationInfo).toString();
         final Drawable icon = getPackageManager().getApplicationIcon(info.activityInfo.applicationInfo);
         apps.add(new AppInfo(packageName, appName, icon));
     }
     apps.sort(new Comparator<AppInfo>() {
         @Override
         public int compare(AppInfo app1, AppInfo app2) {
             return app1.appName.compareTo(app2.appName);
         }
     });
     new AppsDialog(this, apps).show();
 }

 public void onAppSelected(AppInfo selectedApp) {
     this.selectedApp = selectedApp;
     Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
     intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, selectedApp.packageName);
         startActivityForResult(intent, DEF_SMS_REQ);
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     super.onActivityResult(requestCode, resultCode, data);
     if (requestCode == DEF_SMS_REQ) {
         String currentDefault = Telephony.Sms.getDefaultSmsPackage(this);
         boolean isDefault = selectedApp.packageName.equals(currentDefault);

         String msg = selectedApp.appName + (isDefault ?
                 " successfully set as default" :
                 " not set as default");

         Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
     }
 }

 public static class AppInfo {
     String appName;
     String packageName;
     Drawable icon;

     public AppInfo(String packageName, String appName, Drawable icon) {
         this.packageName = packageName;
         this.appName = appName;
         this.icon = icon;
     }

     @NonNull
     @Override
     public String toString() {
         return appName;
     }
 }

您的 Activity 还必须实现 OnAppSelectedListener 接口。

public class MainActivity extends AppCompatActivity implements AppsDialog.OnAppSelectedListener { ... }

接下来,创建一个扩展 Dialog 的 AppsDialog 类:

public class AppsDialog extends Dialog implements AdapterView.OnItemClickListener {
public interface OnAppSelectedListener {
    void onAppSelected(MainActivity.AppInfo selectedApp);
}

private final Context context;
private final List<MainActivity.AppInfo> apps;

public AppsDialog(Context context, List<MainActivity.AppInfo> apps) {
    super(context);

    if (!(context instanceof OnAppSelectedListener)) {
        throw new IllegalArgumentException(
                "Activity must implement OnAppSelectedListener interface");
    }

    this.context = context;
    this.apps = apps;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setTitle("Select default SMS app");

    final ListView listView = new ListView(context);
    listView.setAdapter(new AppsAdapter(context, apps));
    listView.setOnItemClickListener(this);
    setContentView(listView);
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    ((OnAppSelectedListener) context).onAppSelected(apps.get(position));
    dismiss();
}

private static class AppsAdapter extends ArrayAdapter<MainActivity.AppInfo> {
    public AppsAdapter(Context context, List<MainActivity.AppInfo> list) {
        super(context, R.layout.list_item, R.id.text, list);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        final MainActivity.AppInfo item = getItem(position);

        View v = super.getView(position, convertView, parent);
        ((ImageView) v.findViewById(R.id.icon)).setImageDrawable(item.icon);

        return v;
    }
}

}

AppsDialog 类的线性布局(list_item):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingTop="1dp"
android:paddingBottom="1dp"
android:paddingStart="8dp"
android:paddingEnd="8dp">

<ImageView android:id="@+id/icon"
    android:layout_width="36dp"
    android:layout_height="36dp"
    android:contentDescription="Icon Here" />

<TextView android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:textAppearance="?android:attr/textAppearanceListItemSmall"
    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    android:ellipsize="marquee" />

差不多就是这样了。 这一切都是通过以下方式实现的:

对于方法2,接受答案

对于android 10,已接受答案

我修改了代码以满足我的需求。


0
投票

这是正确执行此操作的正确方法。但请记住也要修改您的清单。如果不修改菜单,您将无法将应用程序设置为默认短信应用程序。这是我在 kotlin 中获得许可的课程

class GetPermission(val activity: AppCompatActivity) {




    private val permissions = arrayOf(
        Manifest.permission.READ_SMS,
        Manifest.permission.RECEIVE_SMS,
        Manifest.permission.SEND_SMS,
        Manifest.permission.READ_CONTACTS

    )
    private var requestCode = 100;

    fun askPermission() {
        for (permission in permissions) {
            if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(activity, permissions, requestCode)
            }
        }


        changeDefaultSmsApp()

    }


private val resultLauncher: ActivityResultLauncher<Intent> =
    activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // The user has successfully changed the default SMS app
        } else {
            // The user did not change the default SMS app
        }
    }


fun changeDefaultSmsApp() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val roleManager = activity.getSystemService(RoleManager::class.java)
        if (roleManager.isRoleAvailable(RoleManager.ROLE_SMS)) {
            val roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS)
            resultLauncher.launch(roleRequestIntent)
        }
    } else {
        val myPackageName = activity.packageName
        val setSmsAppIntent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
        setSmsAppIntent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, myPackageName)
        resultLauncher.launch(setSmsAppIntent)
    }
}

}

您需要在清单中添加这些权限

`

<uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_MMS" />
    <uses-permission android:name="android.provider.Telephony.SMS_RECEIVED" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

` 现在添加这些服务和接收器以及一个活动。请记住,这些是必须的,您不能跳过它们。

        <activity android:name=".activiTy.ViewConversation"
        android:exported="true">

        <intent-filter>
            <action android:name="android.intent.action.SENDTO" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="smsto" />
        </intent-filter>
    </activity>

    <service android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
        android:exported="true"
        android:name=".utils.Response">
        <intent-filter>
            <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="smsto" />
        </intent-filter>
    </service>

    <receiver android:permission="android.permission.BROADCAST_SMS"
        android:exported="true"
        android:name=".notification.showNotification">
        <intent-filter>
            <action android:name="android.provider.Telephony.SMS_DELIVER" />
        </intent-filter>
    </receiver>
    <receiver android:permission="android.permission.BROADCAST_WAP_PUSH"
        android:exported="true"
        android:name=".utils.SendSms">
        <intent-filter>
            <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
            <data android:mimeType="application/vnd.wap.mms-message" />
        </intent-filter>
    </receiver>

如果您是 Android 开发新手,请记住将

android:name
属性值替换为您的类名


-1
投票

你想要的方式,这是不可能的。将您自己的应用程序设置为给定意图的默认应用程序的唯一方法是使用 root 访问权限。

提示用户执行此操作的唯一方法是启动您的应用程序响应的意图,并让用户选择您的应用程序在启动意图时始终打开。

© www.soinside.com 2019 - 2024. All rights reserved.