I want to block SMS by contentObserver. For that I want to get the phone number of the SMS first. What do I do to get the number? This is the code that I have, just counting the number of SMS.
package com.SMSObserver4;
import android.app.Activity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Contacts;
import android.provider.Contacts.People.Phones;
public class SMSObserver4 extends Activity {
/** Called when the activity is first created. */
private static final String Address = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setReceiver();
}
private SmsSentCounter smsSentObserver = new SmsSentCounter(new Handler());
private int sms_sent_counter = 0;
private void setReceiver() {
this.getContentResolver().registerContentObserver(
Uri.parse("content://sms"), true, smsSentObserver);
}
class SmsSentCounter extends ContentObserver {
public SmsSentCounter(Handler handler) {
super(handler);
// TODO Auto-generated constructor stub
}
#Override
public void onChange(boolean selfChange) {
// TODO Auto-generated method stub
try{
System.out.println ("Calling onChange new");
super.onChange(selfChange);
Cursor sms_sent_cursor = SMSObserver4.this.managedQuery(Uri
.parse("content://sms"), null, "type=?",
new String[] { "2" }, null);
if (sms_sent_cursor != null) {
if (sms_sent_cursor.moveToFirst()) {
sms_sent_counter++;
System.out.println("test" + sms_sent_counter);
}
}
Uri phoneUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, Address);
if (phoneUri != null) {
Cursor phoneCursor = getContentResolver().query(phoneUri, new String[] {Phones._ID, Contacts.Phones.PERSON_ID}, null, null, null);
if (phoneCursor.moveToFirst()) {
long person = phoneCursor.getLong(1); // this is the person ID you need
}
}
}catch(Exception e)
{}
}
}
}
I have done a lot of tests and I found this to be impossible. That's because when the messaging application inserts a new record in the SMS content provider, it is already trying to send the SMS. So, even if you detect the SMS in the content://sms/outbox URI, it will be too late to stop it. In fact, there's no way to stop it... it all depends on the SMS application, which you can't interrupt.
Nope, you cant. Observer will comeinto affect after dataset has been modified, by that time sms will already be on the way for delivery. Infact by any means you cant block outgoing sms.
Related
I am getting the Sent and Received SMS from almost devices. but i am not able to get it from specific device in specific model. Like samsungs S7, S8, S9. and some LG devices.
Strange is some S7 device works and some not.
Below is the way i am using.
Registering observer in Application class.
private void registerMessageObserver() {
String url = "content://sms/";
Uri uri = Uri.parse(url);
this.getApplicationContext()
.getContentResolver()
.registerContentObserver(uri, true,
new MessageObserver(new Handler(), this));
}
//Observer class
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
public class MessageObserver extends ContentObserver {
private static final String TAG = "MessageObserver";
Context moContext;
// Observe message state incoming or outgoing
public MessageObserver(Handler handler, Context foContext) {
super(handler);
moContext = foContext;
}
#Override
public boolean deliverSelfNotifications() {
Log.i(TAG, "deliverSelfNotifications Changed");
return true;
}
#Override
public void onChange(boolean selfChange) {
Log.i(TAG, "Message Changed");
super.onChange(selfChange);
Log.i(TAG, "Message Changed after super");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && moContext .checkCallingOrSelfPermission(Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED)
return;
String[] laColumns = new String[]{"_id", "type", "address", "body", "date", "person"};
Uri loUriAllMessages = Uri.parse("content://sms/");
Cursor loCursor = moContext.getContentResolver().query(loUriAllMessages, laColumns, null, null, "_id DESC");
if (loCursor != null) {
if (loCursor.moveToFirst()) {
int liMessageId = loCursor.getInt(loCursor.getColumnIndex("_id"));
String lsType = loCursor.getString(loCursor.getColumnIndex("type")).trim();
//Doing my stuff here
}
}
if (loCursor != null)
loCursor.close();
}
}
It work like charm as i said in most of devices. but some device did not call this even onChange did not calling.
I tried below way but it will not even call onChanged in any scenario.
private void registerMessageObserverSent() {
String url = "content://sms/sent";
Uri uri = Uri.parse(url);
this.getApplicationContext()
.getContentResolver()
.registerContentObserver(uri, true,
new MessageObserverSent(new Handler(), this));
}
private void registerMessageObserverOut() {
String url = "content://sms/out";
Uri uri = Uri.parse(url);
this.getApplicationContext()
.getContentResolver()
.registerContentObserver(uri, true,
new MessageObserverOut(new Handler(), this));
}
I tried Broadcast receiver but the receiver is only for the Received message.
Can anyone help how to resolve the issue for those devices.
The app is offline so no issue with play store policy. its for my personal use.
I am trying to add content observer for AOSP Browser's history provider i.e., with Uri Browser.BOOKMARKS_URI. If I attach an observer, the onChange(boolean) gets called on my ICS running my Samsung GT-S7562, my JB running Samsung GT-I8262 or HTC Desire X but I don't get any notifications for AOSP Browser provider on my friend's Android 4.3 running Samsung SM-G7102. However for Google Chrome's provider, i.e., residing at content://com.android.chrome.browser/bookmarks, I get notified for changes on all android releases. Also if I query the AOSP Browser database & scan for entries, it only returns those opened in Chrome (I mean it returns Chrome's history in Browser.BOOKMARKS_URI provider).
Below is the sample service I tested for reference which is not actually required (don't mind but I think everything is quite clear above already):
package vpz.hp;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class Watcher extends Service {
private Provider Browser;
private Provider Chrome;
#Override public IBinder onBind(Intent intent) {
return null;
}
#Override public void onDestroy() {
if (this.Browser != null)
this.Browser.Stop();
if (this.Chrome != null)
this.Chrome.Stop();
super.onDestroy();
}
public final int onStartCommand(Intent Intention, int StartId, int Flags) {
this.Browser = new Provider(super.getApplicationContext(), android.provider.Browser.BOOKMARKS_URI);
this.Browser.Start();
if (Search(getApplicationContext(), "com.android.chrome")) {
this.Chrome = new Provider(super.getApplicationContext(), Uri.parse("content://com.android.chrome.browser/bookmarks"));
this.Chrome.Start();
}
return START_STICKY;
}
private static final boolean Search(Context Sender, String Package) {
try {
return Sender.getPackageManager().getPackageInfo(Package, PackageManager.GET_ACTIVITIES) != null;
} catch (NameNotFoundException Error) {
return false;
}
}
private static class Provider extends ContentObserver {
private Context Sender;
private Uri URI;
public Provider(Context Sender, Uri URI) {
super(new Handler());
this.Sender = Sender;
this.URI = URI;
}
#Override public void onChange(boolean Self) {
String Message = this.URI.toString() + " onChange(" + Self + ")";
Toast.makeText(this.Sender, Message, Toast.LENGTH_SHORT).show();
Log.e("VPZ", Message);
}
public final void Start() {
this.Sender.getContentResolver().registerContentObserver(this.URI, true, this);
}
public final void Stop() {
this.Sender.getContentResolver().unregisterContentObserver(this);
}
}
}
I have added below permission(s) already in the manifest:
<uses-permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS" />
Is content observer on AOSP Browser has been deprecated?
Hie..
I am making an app in which I am detecting whether SIM has changed or not..?
On installation of my app I am storing the current SIM serial number in shared preferences.
On boot I have registered a broadcast receiver. In onReceive() method I am accessing current SIM serial number and comparing it with the stored one on the time of installation,
Below is my code of receiver :
package com.secuirity.sms;
import org.apache.harmony.xnet.provider.jsse.GMailSender;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Log;
public class BootUpReciever extends BroadcastReceiver{
Context context;
String email;
String currentSimSerial;
SharedPreferences settings;
SmsManager smsMgr = SmsManager.getDefault();
public static final String PREFS_NAME = "MyPrefsFile";
#Override
public void onReceive(Context context, Intent intent) {
settings = context.getSharedPreferences(PREFS_NAME, 0);
String storedSimSerial = settings.getString("storedSimSerial", null);
Log.d("Stored Sim Serial::",storedSimSerial);
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
currentSimSerial = tm.getSimSerialNumber();
Log.d("Current Sim Serial","::"+currentSimSerial);
String trustedNum = settings.getString("cellno", null);
email = settings.getString("email", null);
if(currentSimSerial == storedSimSerial){
}else{
Log.d("Sim changed","!!!");
new GmailAsync().execute("");
String sms = "Sim card has changed, " +
"Sim Serial Number of this card is\n"+currentSimSerial+
"Network Operator"+tm.getNetworkOperatorName();
smsMgr.sendTextMessage(trustedNum, null,sms, null, null);
}
Intent sms = new Intent(context, SMSReceiver.class);
sms.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(sms);
Intent netAvailability = new Intent(context, CheckingNetworkAvailability.class);
netAvailability.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(netAvailability);
}
public class GmailAsync extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
String mail_body = "Sim serial number is "+currentSimSerial;
String subject = "Your Sim has changed!!!";
GMailSender sender = new GMailSender("securemob.viasms#gmail.com", "smsfun890");
try {
sender.sendMail(subject,
mail_body+"\nThanks for using Mobile Security App",
"securemob.viasms#gmail.com",
email,null);
} catch (Exception e) {
Log.e("SendMail", e.getMessage(), e);
}
return null;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
Log.d("Mail","Sent");
}
}
}
But Its not working.... :(:(:(
I have the following permissions READ_PHONE_STATE" and "RECEIVE_BOOT_COMPLETED"
I cant see anything wrong in your code, but the first thing I would check is that you have the permission to read the SIM card set in the Manifest.
Hie Guys I got the solution of BOOT UP Receiver....
When android mobile boots then this event is broadcasts to every app, But app those are installed in the internal memory responds soon as compared to the app stored on SD card.
Hence solution was
android:installLocation="internalOnly"
In manifest file as manifest attribute.
i got a class i made, that makes a simple GET request and displays toast messege with the response...
if i call the function from a bottom event click it displays the messege with the data returned, just ok.
but if i call the same function from a brodcast reciver class, it just showing the massege with the data '' (null)
i belive that it showing the massege before i could get the data, and with the button it waits for the data..
how can i make it work from the brodcast reciver?
the class:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.content.Context;
import android.widget.Toast;
public class myclass{
public static void doHttpRequest(String param1, Context context){
String ret="";
try {
URL url = new URL("http://website.com/page?param="+param1);
HttpURLConnection con = (HttpURLConnection) url
.openConnection();
ret=readStream(con.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
CharSequence text = "return data- "+ret;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
private static String readStream(InputStream in) {
BufferedReader reader = null;
String line = "";
String alllines = "";
try {
reader = new BufferedReader(new InputStreamReader(in));
while ((line = reader.readLine()) != null) {
alllines=alllines+line;
}
return alllines;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return alllines;
}
}
from the button it works fine:
final Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
myclass.doHttpRequest("blabla", getBaseContext());
}});
from the brodcast reciver witch in different class it won't return data, but shows the toast..
public class CustomBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CustomBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
myclass.doHttpRequest("blabla", context);
break;
} }
}
please HELP.... :) THANKS
All fixed.. it's seems to be a project settings error, or premmisions error (but i had the premissions in the manifest... must not apply in the apk while compiling)
i copied the classes to enother project made by erlier version of eclipse, and it's works there like a charm...
thanks anyway..
i tried for hours to fix it in the code.. and it was the settings....
I created a myclass.java and CustomBroadcastReceiver.java and tried your code by removing the break statement and one extra curly brace from the CustomBroadcastReceiver.java class and it worked fine for me.
The following code in Activity class demonstrates registering, uninteresting receiver and a Handler for a sample/test broadcast.
CustomBroadcastReceiver customBroadcastReceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customBroadcastReceiver = new CustomBroadcastReceiver();
registerReceiver(cusoBroadcastReceiver, new IntentFilter("com.example.app.testbroadcast"));
// For test broadcast only.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
sendBroadcast(new Intent("com.example.app.testbroadcast"));
}
}, 2000);
}
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unregisterReceiver(customBroadcastReceiver);
}
Hope this helps.
I am able to get a generic notification "that there was a change to the contacts DB", but I want to know the specific record that was inserted, updated, or deleted.
I don't want to use Look-up URI concept because I don't want to set look-up URI for every contact individually. I want a generic solution that I can know when any contact is updated or deleted.
You can implement an Service to watch the database status.
import android.app.Service;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.os.IBinder;
import android.provider.ContactsContract;
public class ContactService extends Service {
private int mContactCount;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mContactCount = getContactCount();
this.getContentResolver().registerContentObserver(
ContactsContract.Contacts.CONTENT_URI, true, mObserver);
}
private int getContactCount() {
Cursor cursor = null;
try {
cursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, null, null, null,
null);
if (cursor != null) {
return cursor.getCount();
} else {
return 0;
}
} catch (Exception ignore) {
} finally {
if (cursor != null) {
cursor.close();
}
}
return 0;
}
private ContentObserver mObserver = new ContentObserver(new Handler()) {
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
final int currentCount = getContactCount();
if (currentCount < mContactCount) {
// DELETE HAPPEN.
} else if (currentCount == mContactCount) {
// UPDATE HAPPEN.
} else {
// INSERT HAPPEN.
}
mContactCount = currentCount;
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(mObserver);
}
}
I implemented this problem in the following way:
During the installation of an app my local DB's Contact table is being initialized by the contacts of the given time. Then all the calls are being tracked by a CallListner : if user gets/makes calls I check if the number is in the current Phone Book of a user,if so I retrieve all contact information related to that number and update my local DB.