java.lang.SecurityException: отказ в разрешении, android.intent.action.PHONE_STATE только для версии kitkat
Я разрабатываю приложение SIP, и оно успешно работает, но получаю исключение PHONE_STATE для отказа в разрешении безопасности только в версии KitKat для Android. Кто-нибудь знает, в чем причина, Пожалуйста, помогите мне найти решение.
Вот некоторая часть кода:
Intent intent = new Intent(ACTION_PHONE_STATE_CHANGED);
intent.putExtra("state",state);
if (number != null)
intent.putExtra("incoming_number", number);
intent.putExtra(mContext.getString(R.string.app_name), true);
mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
LogCat:-
05-28 01:48:52.556: E/AndroidRuntime(2860): FATAL EXCEPTION: main
05-28 01:48:52.556: E/AndroidRuntime(2860): Process: org.sipdroid.sipua, PID: 2860
05-28 01:48:52.556: E/AndroidRuntime(2860): java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.PHONE_STATE from pid=2860, uid=10051
05-28 01:48:52.556: E/AndroidRuntime(2860): at android.os.Parcel.readException(Parcel.java:1461)
05-28 01:48:52.556: E/AndroidRuntime(2860): at android.os.Parcel.readException(Parcel.java:1415)
05-28 01:48:52.556: E/AndroidRuntime(2860): at android.app.ActivityManagerProxy.broadcastIntent(ActivityManagerNative.java:2373)
05-28 01:48:52.556: E/AndroidRuntime(2860): at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1141)
05-28 01:48:52.556: E/AndroidRuntime(2860): at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:370)
05-28 01:48:52.556: E/AndroidRuntime(2860): at org.sipdroid.sipua.ui.Receiver.broadcastCallStateChanged(Receiver.java:496)
2 ответа
Вы не можете сделать это. На KitKat только системные сервисы могут отправлять трансляции.
Вам нужно найти обходной путь для этого.
Измените ваш метод makeCallWithOptions() класса SipService следующим образом...
public void makeCallWithOptions(final String callee, final int accountId, final Bundle options)
throws RemoteException {
SipService.this.enforceCallingOrSelfPermission(SipManager.PERMISSION_USE_SIP, null);
//We have to ensure service is properly started and not just binded
SipService.this.startService(new Intent(SipService.this, SipService.class));
if(pjService == null) {
Log.e(THIS_FILE, "Can't place call if service not started");
// TODO - we should return a failing status here
return;
}
if(!supportMultipleCalls) {
// Check if there is no ongoing calls if so drop this request by alerting user
SipCallSession activeCall = pjService.getActiveCallInProgress();
if(activeCall != null) {
if(!CustomDistribution.forceNoMultipleCalls()) {
notifyUserOfMessage(R.string.not_configured_multiple_calls);
Log.d("call......", "makecallwithoption");
}
return;
}
}
Intent intent = new Intent(SipManager.ACTION_SIP_CALL_LAUNCH);
intent.putExtra(SipProfile.FIELD_ID, accountId);
intent.putExtra(SipManager.EXTRA_SIP_CALL_TARGET, callee);
intent.putExtra(SipManager.EXTRA_SIP_CALL_OPTIONS, options);
sendOrderedBroadcast (intent , SipManager.PERMISSION_USE_SIP, mPlaceCallResultReceiver, null, Activity.RESULT_OK, null, null);
}
Добавить следующий широковещательный приемник..... частный BroadcastReceiver mPlaceCallResultReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, final Intent intent) {
final Bundle extras = intent.getExtras();
final String action = intent.getAction();
if(extras == null) {
Log.e(THIS_FILE, "No data in intent retrieved for call");
return;
}
if(!SipManager.ACTION_SIP_CALL_LAUNCH.equals(action)) {
Log.e(THIS_FILE, "Received invalid action " + action);
return;
}
final int accountId = extras.getInt(SipProfile.FIELD_ID, -2);
final String callee = extras.getString(SipManager.EXTRA_SIP_CALL_TARGET);
final Bundle options = extras.getBundle(SipManager.EXTRA_SIP_CALL_OPTIONS);
if(accountId == -2 || callee == null) {
Log.e(THIS_FILE, "Invalid rewrite " + accountId);
return;
}
getExecutor().execute(new SipRunnable() {
@Override
protected void doRun() throws SameThreadException {
pjService.makeCall(callee, accountId, options);
}
});
}
};
В классе UAStateReceiver измените следующее
private void onBroadcastCallState(final SipCallSession callInfo) {
SipCallSession publicCallInfo = new SipCallSession(callInfo);
Intent callStateChangedIntent = new Intent(SipManager.ACTION_SIP_CALL_CHANGED);
callStateChangedIntent.putExtra(SipManager.EXTRA_CALL_INFO, publicCallInfo);
pjService.service.sendBroadcast(callStateChangedIntent, SipManager.PERMISSION_USE_SIP);
}
а также......
private void broadCastAndroidCallState(String state, String number) {
// Android normalized event
if(!Compatibility.isCompatible(19)) {
// Not allowed to do that from kitkat
Intent intent = new Intent(ACTION_PHONE_STATE_CHANGED);
intent.putExtra(TelephonyManager.EXTRA_STATE, state);
if (number != null) {
intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, number);
}
intent.putExtra(pjService.service.getString(R.string.app_name), true);
pjService.service.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
}
}
и он сможет сделать звонок в Android 4.4.2 Happy Coading:)