my phone is android 5.0 API 22.
I just learn build app Android
I create app fake SMS but crash :(
java.lang.SecurityException: Permission Denial: writing com.android.providers.telephony.SmsProvider uri content://sms/outbox from pid=23774, uid=10308 requires android.permission.WRITE_SMS, or grantUriPermission()
My code:
MainActivity
I want test send sms default from phone number 0901123456 and message "test sent" to my phone.
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
public static final String TAG = MainActivity.class.getName();
public static final int PERMISSION_RESULT_CODE = 123;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupView();
setDefaultApp();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{
Manifest.permission.BROADCAST_SMS,
Manifest.permission.READ_SMS,
Manifest.permission.SEND_SMS,
Manifest.permission.RECEIVE_SMS}, PERMISSION_RESULT_CODE);
}
}
}
private void setupView(){
findViewById(R.id.button_draft).setOnClickListener(this);
findViewById(R.id.button_inbox).setOnClickListener(this);
findViewById(R.id.button_outbox).setOnClickListener(this);
findViewById(R.id.button_sent).setOnClickListener(this);
}
private void setDefaultApp(){
final String myPackageName = getPackageName();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (!Telephony.Sms.getDefaultSmsPackage(this).equals(myPackageName)) {
Intent intent =
new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,
myPackageName);
startActivity(intent);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == PERMISSION_RESULT_CODE){
for (int i= 0; i< permissions.length; i++) {
Log.d(TAG, permissions[i] + " " + grantResults[i]);
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button_draft:
ContentValues values1 = new ContentValues();
values1.put("address", "0901123456");
values1.put("body", "test draft");
getContentResolver().insert(Uri.parse("content://sms/draft"), values1);
break;
case R.id.button_inbox:
ContentValues values2 = new ContentValues();
values2.put("address", "0901123456");
values2.put("body", "test inbox");
getContentResolver().insert(Uri.parse("content://sms/inbox"), values2);
break;
case R.id.button_outbox:
ContentValues values3 = new ContentValues();
values3.put("address", "0901123456");
values3.put("body", "test outbox");
getContentResolver().insert(Uri.parse("content://sms/outbox"), values3);
break;
case R.id.button_sent:
ContentValues values4 = new ContentValues();
values4.put("address", "0901123456");
values4.put("body", "test sent");
getContentResolver().insert(Uri.parse("content://sms/sent"), values4);
break;
}
}
}
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<receiver
android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver
android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<receiver
android:name=".FinderReceiver"
android:enabled="true"
android:permission="android.permission.RECEIVE_SMS">
<intent-filter>
<action
android:name="android.provider.Telephony.SMS_RECEIVED"
android:priority="999" />
</intent-filter>
</receiver>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity
android:name=".ComposeSmsActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service
android:name=".HeadlessSmsSendService"
android:exported="true"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
Who can help me? :((
Thank you so much!
You can only write to the SMS provider if your app is the user's chosen SMS client: https://android-developers.googleblog.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html
Related
I am implementing push notification on Android with FirebaseMessagingService for an app that mainly lives in a webview.
The notifications arrives as expected when the app is in foreground, background and closed (wiped away).
Tapping a notification opens the deeplink provided in data.payload.link (after parsing the JSON in data.payload) when the app is in forground and background but not when closed.
In case the app is closed - the app gets started and shows up but the deeplink is not loaded like when the app is in foreground/background.
The payload I send to the Firebase API looks as follows:
admin
.messaging()
.send({
data: {
payload: JSON.stringify({
link: link || "",
}),
},
notification,
android: {
notification: {
click_action: "OPEN_DEEPLINK_FROM_PUSH_NOTIFICATION",
},
priority: "normal",
},
token: recipient,
})
The onMessageReceived() is implemented as follows:
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage == null) return;
Map<String, String> data = remoteMessage.getData();
String payload = (String) data.values().toArray()[0];
String link = null;
JSONObject jObject = null;
try {
jObject = new JSONObject(payload);
link = jObject.getString("link");
} catch (Exception e) {
Log.e(PUSH_NOTIFICATION, "ERROR: " + e.getMessage());
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(link));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle(remoteMessage.getNotification().getTitle())
.setContentText(remoteMessage.getNotification().getBody())
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, builder.build());
notificationId = ++notificationId;
}
The androidManifest.xml looks like:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.myapp" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.AppCompat" >
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_ic_notification" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorNotification" />
<activity
android:name="com.myapp.app.mobile.MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|screenSize"
android:theme="#style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="OPEN_DEEPLINK_FROM_PUSH_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="app.myapp.com" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="app.myapp.com" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="app.myapp.ch" />
</intent-filter>
<intent-filter android:label="">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="app.myapp.ch" />
</intent-filter>
</activity>
<service
android:name="com.myapp.app.mobile.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
Opening deeplinks when an app is not running is handled in onPageFinished() of my WebViewClient instance (what works for openening deeplinks eg. from email when the app is not running):
webView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
if(intent.getData() != null){
openDeeplink(intent);
}
}
I am wondering why this logic does not work in case of tapping a notification when the app was not running?
Any suggestions are welcome.
As firebese the docs describe here: https://firebase.google.com/docs/cloud-messaging/android/receive the data is delivered within the extras of the intent. This also applies for apps that are NOT running. I think the docs are not precise enough in this matter.
The following fix did the trick in this case:
public void onPageFinished(WebView view, String url) {
Intent intent = getIntent();
if(intent.getData() != null || intent.getExtras() != null){
openDeeplink(intent);
}
I am developing an SMS messaging application. The problem arose with BroadcastReceiver which check sent message or no. When I registrer him in activity, he works good. But I want to saddle him in the department class so that he will not be destroyed in the event of the closure of activity. Please help =(
public void send(View view) {
String SENT = "SMS_SENT";
String DELIVERED = "SMS_DELIVERED";
msg = mEditMessage.getText().toString();
SmsManager sm = SmsManager.getDefault();
ArrayList<String> parts = sm.divideMessage(msg);
Intent iSent = new Intent(SENT);
iSent.putExtra("id", lastId + 1);
PendingIntent piSent = PendingIntent.getBroadcast(this, 0, iSent, 0);
Intent iDel = new Intent(DELIVERED);
iDel.putExtra("msg", msg);
PendingIntent piDel = PendingIntent.getBroadcast(this, 0, iDel, 0);
progressSms = new Sms(lastId + 1, extraAddress, msg, "1", Calendar.getInstance().getTime(), 2, imageUri, extraName, true);
updateAdapter(progressSms);
if (parts.size() == 1)
{
msg = parts.get(0);
sm.sendTextMessage(extraAddress, null, msg, piSent, piDel);
compileMessage();
}
else
{
ArrayList<PendingIntent> sentPis = new ArrayList<PendingIntent>();
ArrayList<PendingIntent> delPis = new ArrayList<PendingIntent>();
int ct = parts.size();
for (int i = 0; i < ct; i++)
{
sentPis.add(i, piSent);
delPis.add(i, piDel);
}
sm.sendMultipartTextMessage(extraAddress, null, parts, sentPis, delPis);
public class SentSmsReciver extends BroadcastReceiver {//
private String LOG_TAG = "sent_reciver";
private SentListener sentListener;
public SentSmsReciver(SentListener sentListener) {
Log.i(LOG_TAG, "create reciver");
this.sentListener = sentListener;
}
private boolean failed = true;
private Context context;
private String id;
private SQLiteDatabase db;
#Override
public void onReceive(Context context, Intent intent) {
Log.i(LOG_TAG, "create reciver");
this.context = context;
db = new SmsDbHelper(context.getApplicationContext()).getWritableDatabase();
id = intent.getStringExtra("id");
switch(getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(context,"SMS sent",
Toast.LENGTH_SHORT).show();
failed = false;
compileMessage();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(context,"Generic failure",
Toast.LENGTH_SHORT).show();
compileMessage();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(context,"No service",
Toast.LENGTH_SHORT).show();
compileMessage();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(context,"Null PDU",
Toast.LENGTH_SHORT).show();
compileMessage();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(context,"Radio off",
Toast.LENGTH_SHORT).show();
compileMessage();
break;
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.ciphermessanger">
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name=".activity.MyIntentService"
android:exported="false"></service>
<receiver
android:name=".recivers.SentSmsReciver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="SMS_SENT" />
</intent-filter>
</receiver>
<receiver
android:name=".recivers.DeliverSmsReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="SMS_DELIVERED" />
</intent-filter>
</receiver>
<activity android:name=".activity.DialogActivity" />
<activity android:name=".activity.SmsListActivity" />
<receiver
android:name=".recivers.SmsReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<receiver
android:name=".recivers.MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<activity android:name=".activity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".services.HeadlessSmsSendService"
android:exported="true"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
<activity android:name=".activity.ComposeSmsActvity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
</application>
</manifest>
if someone will be mean
Start service and there register broadcast
public class MyIntentService extends Service {
String SENT = "SMS_SENT";
BroadcastReceiver broadcastReceiver;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
broadcastReceiver = new SentSmsReciver();
registerReceiver(broadcastReceiver, new IntentFilter(SENT));
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
}
I'm currently having trouble getting the app to send the user a dialogue to set the default handler for SMS on API 29.
I initially followed https://developer.android.com/guide/topics/permissions/default-handlers.
It didn't work so I looked around and saw this: How to set Default SMS prompt for KitKat.
So I followed https://android-developers.googleblog.com/2013/10/getting-your-sms-apps-ready-for-kitkat.html and added the snippet to my manifest XML (without actual implementation, as the StackOverflow user said in the post). Unfortunately every time I click the button that starts the ACTION_CHANGE_DEFAULT intent, nothing happens except he log.
My main activity has the following onCreate:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var btn = findViewById<Button>(R.id.button3)
btn.setOnClickListener {
Log.d("TAG", "Sending change default intent")
val setSmsAppIntent = Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT)
setSmsAppIntent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, packageName)
startActivityForResult(setSmsAppIntent, CHANGE_SMS_DEFAULT_RESULT)
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testapplication">
<uses-permission android:name="android.permission.READ_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name=".FetchSMS"
android:exported="false"></service>
<activity
android:name=".DisplayMessageActivity"
android:parentActivityName=".MainActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- These are ONLY used to set app as default SMS -->
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".ComposeSmsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
</manifest>
Log:
Would appreciate some help. Thanks in advance.
My minSdkVersion is 19
Edit: I just tried this on the emulator on KitKat (API 19) and it worked - but it doesn't on Q (API 29)
Try below piece of code.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
RoleManager roleManager = mContext.getSystemService(RoleManager.class);
// check if the app is having permission to be as default SMS app
boolean isRoleAvailable = roleManager.isRoleAvailable(RoleManager.ROLE_SMS);
if (isRoleAvailable){
// check whether your app is already holding the default SMS app role.
boolean isRoleHeld = roleManager.isRoleHeld(RoleManager.ROLE_SMS);
if (isRoleHeld){
Intent roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS);
startActivityForResult(roleRequestIntent,requestCode);
}
}
} else {
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, defaultSystemApp);
startActivityForResult(intent, requestCode);
}
Add this permission is manifest
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.app.role.SMS"/>
</intent-filter>
I had to modify Praveen's code to make it work. Main difference is with if(isRoleHeld). Here is how it look like.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
RoleManager roleManager = getApplicationContext().getSystemService(RoleManager.class);
// check if the app is having permission to be as default SMS app
assert roleManager != null;
boolean isRoleAvailable = roleManager.isRoleAvailable(RoleManager.ROLE_SMS);
if (isRoleAvailable){
// check whether your app is already holding the default SMS app role.
boolean isRoleHeld = roleManager.isRoleHeld(RoleManager.ROLE_SMS);
if (!isRoleHeld){
Intent roleRequestIntent = roleManager.createRequestRoleIntent(RoleManager.ROLE_SMS);
startActivityForResult(roleRequestIntent,resultCode);
}
}
} else {
Intent intent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getApplicationContext().getPackageName());
startActivityForResult(intent, resultCode);
}
try this code it works fine with me
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){
//String mypackagename = getPackageName();
if(Telephony.Sms.getDefaultSmsPackage(this)!=null){
if (Telephony.Sms.getDefaultSmsPackage(this).equals(getPackageName())){
//todo go nain activity
}else{
Intent setSmsAppIntent = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
setSmsAppIntent.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME,getPackageName());
startActivityForResult(setSmsAppIntent, 1);
}
}else{toast("no tlphony");}
}
else{
RoleManager rolemanager = getApplicationContext().getSystemService(RoleManager.class);
if (rolemanager.isRoleAvailable(RoleManager.ROLE_SMS)){
if (rolemanager.isRoleHeld(RoleManager.ROLE_SMS)){
//todo go nain activity
}
else{
Intent roleRequestIntent = rolemanager.createRequestRoleIntent(RoleManager.ROLE_SMS);
startActivityForResult(roleRequestIntent,1);
}
}
}
I am working on a project in which I have made app to default sms app and getting new message body and notification through Broadcast Receiver. It is showing toast that new message has been received and also read new message body.
But problems are
Problem 1:
The newly received sms is not retrieving from my default sms app inbox and not showing in my listview.
Problem 2:
I am not able to get each and every message from each conversation
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.e(TAG, "Intent recieved: " + intent.getAction());
if (intent.getAction() == SMS_RECEIVED) {
SmsMessage msg = null;
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
if (messages.length > -1) {
Log.e(TAG, "Message recieved: " + messages[0].getMessageBody());
MyNotificationManager.getInstance(context).displayNotification(messages[0].getOriginatingAddress(), messages[0].getMessageBody());
}
}
}
}
Manifest File
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-sdk android:name="org.apache.http.legacy" android:required="false"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:name="com.ughareja.whocaller.utils.App"
android:networkSecurityConfig="#xml/network_security_config"
android:largeHeap="true">
<activity android:name="com.ughareja.whocaller.activities.SplashActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="#string/default_notification_channel_id" />
<receiver android:name=".smsReciever.SmsListener"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".smsReciever.MmsReciever"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".smsReciever.ComposeSmsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".smsReciever.HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
Can you tell me How to save receive message ?
To receive, I suggest changing your manifest:
<receiver android:name=".smsReciever.SmsListener"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<receiver android:name=".smsReciever.MmsReciever"
android:enabled="true"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
In addition, you will need to declare the following permissions:
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH"/>
You shouldn't be doing so much work on the receiver, send it to an intentReceiver instead:
#Override
public void onReceive(Context context, Intent intent) {
Timber.i("Intent received: " + intent.getAction());
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
Bundle bundle = intent.getExtras();
Intent intentServiceIntent = new Intent(context, SMSIntentService.class);
intentServiceIntent.putExtras(bundle);
context.startService(intentServiceIntent);
//send broadcast to networkAvailableReceiver
Intent intentNetworkBroadcastReceiver = new Intent();
intentNetworkBroadcastReceiver.setAction("Youraction.CHECK_NETWORK_CONNECTIVITY");
context.sendBroadcast(intentNetworkBroadcastReceiver);
}
}
Here's what I use to parse out the message:
private fun parseOutMessages(intent : Intent?) {
val msgsAny : Array<Any>
var sender: String?
val msgBody: String
var bundle = Bundle()
if (intent != null) {
bundle = intent.extras as Bundle
}
try {
//parses out the message
val pdus = bundle.get("pdus") as Array<Any>
val msgs = Array<SmsMessage?>(pdus.size, {null})
for (i in msgs.indices) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val format = bundle.getString("format")
msgs[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray, format)
} else {
msgs[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray)
}
// Here you have the sender(phone number)
sender = msgs[i]?.originatingAddress
//is the message long enough to send?
var messageBodyLength = 0
if (msgs[i] != null) {
val message = msgs[i] as SmsMessage
messageBodyLength = message.messageBody.length
}
}
} catch (e: Exception) {
e.printStackTrace()
Timber.e(e)
}
}
I have an listview of SMSItem objects . When any new sms arrives , it is showed in the list . But after clicking the list or if the activity is relaunched , the item is disappearing . The item is not showed in the list .
My manifest file is as follows :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commlink.smscheck"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="20" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".SmsActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SmsBroadcastReceiver"
android:exported="true" >
<intent-filter android:priority="999" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<activity
android:name=".ShowIndividualSMS"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<receiver android:name=".SmsReceiver"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".ComposeSmsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
</manifest>
If the menifest file is as follows , then the item in list is not disappearing . But the app is not set as default .
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commlink.smscheck"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-sdk
android:minSdkVersion="19"
android:targetSdkVersion="20" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".SmsActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SmsBroadcastReceiver"
android:exported="true" >
<intent-filter android:priority="999" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<activity
android:name=".ShowIndividualSMS"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<receiver android:name=".MmsReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- Activity that allows the user to send new SMS/MMS messages -->
<activity android:name=".ComposeSmsActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- Service that delivers messages from the phone "quick response" -->
<service android:name=".HeadlessSmsSendService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
</application>
</manifest>
Where is the problem . How can I solve this?
The code of the adapter is as follows :
public class SmsArrayAdapter extends ArrayAdapter<SMSItem> {
List<SMSItem> smsBody;
Context context;
private static LayoutInflater inflater = null;
String fromNumber;
public SmsArrayAdapter(Context context, int resource,
List<SMSItem> smsBody, String fromNumber) {
super(context, resource, smsBody);
this.smsBody = smsBody;
this.context = context;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.fromNumber = fromNumber;
}
public SMSItem getStr(int position) {
return smsBody.get(position);
}
public void setRead(int position, String smsMessageId) {
smsBody.get(position).status = true;
SMSItem smsItem = smsBody.get(position);
smsItem.status = true;
//smsBody.set(position, smsItem);
ContentValues values = new ContentValues();
values.put("read",true);
int flag = context.getContentResolver().update(Uri.parse("content://sms/inbox"),
values, "_id=" + smsMessageId, null);
Toast.makeText(context, "The result is "+flag, Toast.LENGTH_LONG).show();
/* Uri uri = Uri.parse("content://sms/inbox");
String selection = "address = ? AND body = ? AND read = ?";
String from = "03590000004";
String body =smsItem.sms;
String[] selectionArgs = {from, body, "0"};
ContentValues values = new ContentValues();
values.put("read", true);
int flag = context.getContentResolver().update(uri, values, selection, selectionArgs);
Toast.makeText(context, "The result is "+flag, Toast.LENGTH_LONG).show(); */
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return super.getCount();
}
#Override
public SMSItem getItem(int position) {
// TODO Auto-generated method stub
return smsBody.get(position);
}
public static class ViewHolder {
public TextView textfrom;
public TextView text_sms;
public TextView text_time;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Toast.makeText(context, "The index is "+position, Toast.LENGTH_LONG).show();
ViewHolder holder;
if (convertView == null) {
/****** Inflate tabitem.xml file for each row ( Defined below ) *******/
convertView = inflater.inflate(R.layout.row_item, null);
/****** View Holder Object to contain tabitem.xml file elements ******/
holder = new ViewHolder();
holder.textfrom = (TextView) convertView
.findViewById(R.id.textView_from);
holder.text_sms = (TextView) convertView
.findViewById(R.id.textView_sms);
holder.text_time = (TextView) convertView
.findViewById(R.id.textView_time);
/************ Set holder with LayoutInflater ************/
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textfrom.setText(" " + fromNumber);
SMSItem smsItem = smsBody.get(position);
String smsTextToDisplay = smsItem.sms;
if (smsTextToDisplay.length() > 100)
smsTextToDisplay = smsTextToDisplay.substring(0, 99) + " ...";
holder.text_sms.setText(smsTextToDisplay);
holder.text_time.setText(smsItem.time);
if (smsItem.status == false) {
convertView.setBackgroundColor(context.getResources().getColor(
R.color.light_blue_overlay));
}
else
{
convertView.setBackgroundColor(Color.WHITE);
}
return convertView;
}
}