Sdk 版本 23 中的 Ussd 异常

Posted

技术标签:

【中文标题】Sdk 版本 23 中的 Ussd 异常【英文标题】:Ussd Exception in Sdk Version 23 【发布时间】:2017-08-01 18:50:48 【问题描述】:

我在按钮上有一个 ussd 代码。我在清单中添加了 CALL_PHONE 权限。 我使用 sdk 版本(23)。 此代码无法正常工作。

基本上我应该怎么做?谢谢。

我有以下错误:

?E/androidRuntime: 致命异常: main 进程:com.mahdishekari.mycollectbill,PID:31738 java.lang.SecurityException: Permission Denial: 从 ProcessRecord4e2904f 31738:com.mahdishekari 开始 Intent act=android.intent.action.CALL dat=tel:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx cmp=com.android.server.telecom/.components.UserCallActivity .mycollectbill/u0a109 (pid=31738, uid=10109) 已撤销权限 android.permission.CALL_PHONE 在 android.os.Parcel.readException(Parcel.java:1620) 在 android.os.Parcel.readException(Parcel.java:1573) 在 android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:2776) 在 android.app.Instrumentation.execStartActivity(Instrumentation.java:1509) 在 android.app.Activity.startActivityForResult(Activity.java:3958) 在 android.app.Activity.startActivityForResult(Activity.java:3919) 在 com.mahdishekari.mycollectbill.ActivityMain$C00661.onClick(ActivityMain.java:78) 在 android.view.View.performClick(View.java:5217) 在 android.view.View$PerformClick.run(View.java:21349) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5585) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620) I/Process:发送信号。 PID:31738 SIG:9 与目标VM断开连接,地址:'localhost:8601',传输:'socket'

我的代码:

public class ActivityMain extends ActivityBase 
Button btnLink;
Button btnPayBill;
Button btnRecords;
Button btnScanner;
Button btnSupport;
boolean doubleBackToExitPressedOnce;
DatabaseHelper2 myDbHelper;
TextView tvBillType;
TextView tvPrice;
EditText txtBillID;
EditText txtPayID;
EditText txtPrice;


class C00661 implements OnClickListener 
    C00661() 
    

    public void onClick(View v) 
        String payID = ActivityMain.this.txtPayID.getText().toString();
        String billID = ActivityMain.this.txtBillID.getText().toString();
        String myID = "124336";
        String price = ActivityMain.this.txtPrice.getText().toString();
        if (billID.length() == 0) 
            ActivityMain.this.showToast("\u0634\u0646\u0627\u0633\u0647 \u0642\u0628\u0636 \u0648\u0627\u0631\u062f \u0646\u0634\u062f\u0647 \u0627\u0633\u062a");
         else if (payID.length() == 0) 
            ActivityMain.this.showToast("\u0634\u0646\u0627\u0633\u0647 \u067e\u0631\u062f\u0627\u062e\u062a \u0648\u0627\u0631\u062f \u0646\u0634\u062f\u0647 \u0627\u0633\u062a");
         else if (price.length() == 0) 
            ActivityMain.this.showToast("\u0645\u0628\u0644\u063a \u0648\u0627\u0631\u062f \u0646\u0634\u062f\u0647 \u0627\u0633\u062a");
         else 
            int i;
            int payIdLen = payID.length();
            for (i = 0; i < 13 - payIdLen; i++) 
                payID = "0" + payID;
            
            int billIdLen = billID.length();
            for (i = 0; i < 13 - billIdLen; i++) 
                billID = "0" + billID;
            
            Bill entityBillRercord = new Bill();
            entityBillRercord.billId = billID;
            entityBillRercord.createDate = Tools.getDate();
            entityBillRercord.payId = payID;
            entityBillRercord.refId = "";
            entityBillRercord.price = Tools.toInt(price);
            DbBills.insert(entityBillRercord);
            String encodeHash = Uri.encode("#");
            String ussd = "*733*3*2*" + billID + "*" + payID + "*" + encodeHash;
            ActivityMain.this.startActivityForResult(new Intent("android.intent.action.CALL", Uri.parse("tel:" + ussd)),1);
        
    



class Scanner implements OnClickListener 
    Scanner() 
    

    @Override
    public void onClick(View v) 

        if (v.getId() == R.id.btnReadBarcode) 
            IntentIntegrator scanIntegrator = new IntentIntegrator(ActivityMain.this);
            scanIntegrator.initiateScan();
        
    



class C00683 implements OnClickListener 
    C00683() 
    

    public void onClick(View v) 
        Intent intent = new Intent(ActivityMain.this, ActivitySupport.class);
        startActivity(intent);
        overridePendingTransition(R.anim.slide_in, R.anim.slide_out);

    



class C00694 implements OnClickListener 
    C00694() 
    

    public void onClick(View v) 
        Intent intent = new Intent("android.intent.action.SEND");
        intent.setType("text/plain");
        intent.putExtra("android.intent.extra.SUBJECT", "\u0646\u0631\u0645 \u0627\u0641\u0632\u0627\u0631 \u0647\u0645\u0647 \u0642\u0628\u0636");
        intent.putExtra("android.intent.extra.TEXT", "\u0646\u0631\u0645 \u0627\u0641\u0632\u0627\u0631 \u0647\u0645\u0647 \u0642\u0628\u0636\n\r\u067e\u0631\u062f\u0627\u062e\u062a \u0631\u0627\u062d\u062a \u0648 \u0622\u0633\u0627\u0646 \u06a9\u0644\u06cc\u0647 \u0642\u0628\u0648\u0636 \u0645\u062c\u0647\u0632 \u0628\u0647 \u0628\u0627\u0631\u06a9\u062f \u062e\u0648\u0627\u0646\n\r http://yealame.ir/upload/allbills.apk");
        ActivityMain.this.startActivity(Intent.createChooser(intent, "share"));
    



class C00705 implements OnClickListener 
    C00705() 
    

    public void onClick(View v) 
        Intent intent = new Intent(ActivityMain.this, ActivityRecords.class);
        startActivity(intent);
        overridePendingTransition(R.anim.slide_in, R.anim.slide_out);

    



class C00716 implements TextWatcher 
    C00716() 
    

    public void onTextChanged(CharSequence s, int start, int before, int count) 
    

    public void beforeTextChanged(CharSequence s, int start, int count, int after) 
    

    public void afterTextChanged(Editable s) 
        String payID = ActivityMain.this.txtPayID.getText().toString();
        String price = "";
        if (payID.length() != 0) 
            int i;
            int payIdLen = payID.length();
            for (i = 0; i < 13 - payIdLen; i++) 
                payID = "0" + payID;
            
            for (i = 0; i < 8; i++) 
                price = new StringBuilder(String.valueOf(price)).append(String.valueOf(payID.charAt(i))).toString();
            
            price = String.valueOf(Tools.toInt(price));
            ActivityMain.this.txtPrice.setText(new StringBuilder(String.valueOf(price)).append("00").toString());
            ActivityMain.this.tvPrice.setText("\u0645\u0628\u0644\u063a \u0642\u0628\u0636: " + price + "00 \u062a\u0648\u0645\u0627\u0646");
        
    



class C00727 implements TextWatcher 
    C00727() 
    

    public void onTextChanged(CharSequence s, int start, int before, int count) 
    

    public void beforeTextChanged(CharSequence s, int start, int count, int after) 
    

    public void afterTextChanged(Editable s) 
        String billID = ActivityMain.this.txtBillID.getText().toString();
        int billIdLen = billID.length();
        if (billIdLen != 0) 
            for (int i = 0; i < 13 - billIdLen; i++) 
                billID = "0" + billID;
            
            ActivityMain.this.setBillIcon(Tools.getBillIcon(billID));
        
    



class C00738 implements Runnable 
    C00738() 
    

    public void run() 
        ActivityMain.this.doubleBackToExitPressedOnce = false;
    


public ActivityMain() 
    this.doubleBackToExitPressedOnce = false;


protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    requestWindowFeature(1);
    setContentView(R.layout.main);
    setFont(findViewById(R.id.llMain));
    loadDb();
    this.btnPayBill = (Button) findViewById(R.id.btnPay);
    this.btnScanner = (Button) findViewById(R.id.btnReadBarcode);
    this.txtPayID = (EditText) findViewById(R.id.txtPayID);
    this.txtPrice = (EditText) findViewById(R.id.txtPrice);
    this.txtBillID = (EditText) findViewById(R.id.txtBillID);
    this.tvPrice = (TextView) findViewById(R.id.tvBillPrice);
    this.tvBillType = (TextView) findViewById(R.id.tvBillType);
    this.btnRecords = (Button) findViewById(R.id.btnRecords);
    this.btnLink = (Button) findViewById(R.id.btnLink);
    this.btnSupport = (Button) findViewById(R.id.btnSupport);
    setListeners();


private void loadDb() 
    this.myDbHelper = new DatabaseHelper2(this);
    try 
        this.myDbHelper.createDataBase();
     catch (IOException e) 
    
    try 
        this.myDbHelper.openDataBase();
     catch (SQLException e2) 
    
    BaseDataLayer.db = this.myDbHelper.getDB();


private void setListeners() 
    this.btnPayBill.setOnClickListener(new C00661());
    this.btnScanner.setOnClickListener(new Scanner());
    this.btnSupport.setOnClickListener(new C00683());
    this.btnLink.setOnClickListener(new C00694());
    this.btnRecords.setOnClickListener(new C00705());
    this.txtPayID.addTextChangedListener(new C00716());
    this.txtBillID.addTextChangedListener(new C00727());


private void setBillIcon(int billType) 
    switch (billType) 
        case CursorAdapter.FLAG_AUTO_REQUERY /*1*/:
            this.tvBillType.setBackgroundResource(R.drawable._bill_1_waterpng);
        case CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER /*2*/:
            this.tvBillType.setBackgroundResource(R.drawable._bill_2_electric);
        case TransportMediator.FLAG_KEY_MEDIA_FAST_FORWARD /*3*/:
            this.tvBillType.setBackgroundResource(R.drawable._bill_3_gas);
        case TransportMediator.FLAG_KEY_MEDIA_PLAY /*4*/:
            this.tvBillType.setBackgroundResource(R.drawable._bill_4_tel);
        default:
            this.tvBillType.setBackgroundDrawable(null);
    


public void onActivityResult(int requestCode, int resultCode, Intent intent) 
    IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
    if (scanningResult != null) 
        String scanContent = scanningResult.getContents();
        int contentsLen = scanContent.length();
        for (int i = 0; i < 26 - contentsLen; i++) 
            scanContent = "0" + scanContent;
        
        if (scanContent != null) 
            String txtBillID = scanContent.substring(0, 13);
            String txtPayID = scanContent.substring(18);
            this.txtBillID.setText(txtBillID);
            this.txtPayID.setText(txtPayID);
            this.btnPayBill.setActivated(true);
        
     else 
        Toast toast = Toast.makeText(getApplicationContext(),
                "No scan data received!", Toast.LENGTH_SHORT);
        toast.show();
    



public void onBackPressed() 
    if (this.doubleBackToExitPressedOnce) 
        super.onBackPressed();
        return;
    
    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "\u0628\u0631\u0627\u06cc \u062e\u0631\u0648\u062c \u062f\u0648\u0628\u0627\u0631\u0647 \u06a9\u0644\u06cc\u062f \u0628\u0627\u0632\u06af\u0634\u062a \u0631\u0627 \u0628\u0632\u0646\u06cc\u062f", Toast.LENGTH_LONG).show();
    new Handler().postDelayed(new ActivityMain.C00738(), 2000);

【问题讨论】:

developer.android.com/training/permissions/requesting.html 【参考方案1】:

从 SDK 版本 23 及更高版本开始,您必须向用户请求运行时权限。从 API 级别 23 及更高版本请求是强制性的。

您可以使用此代码,如果 boolean 为 true,那么它将允许您调用。

在这一行之前

if (requestCallPhonePermission(this)) 
ActivityMain.this.startActivityForResult(new Intent("android.intent.action.CALL", Uri.parse("tel:" + ussd)),1);
  


@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static boolean requestCallPhonePermission(final Context context) 
    if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) 
        String callPhonePermission = Manifest.permission.CALL_PHONE;
        int hasPermission = ContextCompat.checkSelfPermission(context, callPhonePermission);
        final String[] permissions = new String[]callPhonePermission;
        if (hasPermission != PackageManager.PERMISSION_GRANTED) 
                ActivityCompat.requestPermissions((Activity) context, permissions, PERMISSION_REQUEST_CALL_PHONE);
            return false;
         else 
            return true;
        
    
    return true;

和 在相同的活动中获得许可也放这个。

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    switch (requestCode) 
        case PERMISSION_REQUEST_CALL_PHONE:
            if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) 
                Snackbar snackbar = Snackbar.make(CoordResident, R.string.permission_goto_setting, Snackbar.LENGTH_LONG);
                snackbar.setAction("Settings", new View.OnClickListener() 
                    @Override
                    public void onClick(View view) 
                        // open settings to enable permisions 
                    
                );
                snackbar.show();
            
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    

【讨论】:

【参考方案2】:

Android Version &gt; 23 中,您必须在运行时请求许可。你没有在运行时询问用户CALL_PHONE 并且应用程序崩溃了。

类似这样的:

Learn more about asking permission at run time.

【讨论】:

以上是关于Sdk 版本 23 中的 Ussd 异常的主要内容,如果未能解决你的问题,请参考以下文章

USSD 消息中的最大字符数是多少?

织物库中的格式错误的异常

Xamarin踩坑经历

处理Android SDK版本和定位

TaskDialog 引发异常:需要版本 6 中的 comctl32.dll

更新 ADT 23 后,首选项中的 SDK 路径缺失 [重复]