I know this question is way old and may be duplicate, but I have a particular query based on it for which I am still trying to find the solution.
As far as I know, ContentObserver on URI content://sms will be triggered when ever there is change in data.
I have tried,
https://katharnavas.wordpress.com/2012/01/18/listening-for-outgoing-sms-or-send-sms-in-android/
Android : Catching Outgoing SMS using ContentObserver or receiver not working
and many more...
As per my understanding this can only be achieved by Content provider and there is no broadcast to handle this. Also content://sms/sent doesn't work at
contentResolver.registerContentObserver(Uri.parse("content://sms/sent"), true, observer);
Am receiving the onChange for each messaging data whether its SMS sent, received, deleted. So as per the documentation of android and other stackoverflow links I found using https://developer.android.com/reference/android/provider/Telephony.TextBasedSmsColumns.html#MESSAGE_TYPE_SENT as comparison method.
So my check goes as,
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Uri uriSMSURI = Uri.parse("content://sms");
Cursor cur = getContentResolver().query(uriSMSURI, null, null, null, null);
cur.moveToFirst();
String id = cur.getString(cur.getColumnIndex("_id"));
String protocol = cur.getString(cur.getColumnIndex("protocol"));
Log.d(TAG, "protocol = " + protocol);
int type = cur.getInt(cur.getColumnIndex("type"));
Log.d(TAG, "onChange: type = " + type);
// I have even tried with protocol == null check.
if (type == 2 && smsChecker(id)) {
Log.d(TAG, "Sent sms");
}
cur.close();
}
private boolean smsChecker(String smsId) {
boolean flagSMS = true;
if (smsId.equals(lastSmsId)) {
flagSMS = false;
}
else {
lastSmsId = smsId;
}
return flagSMS;
}
So my question here is, If I delete any messages or trigger a outgoing message I receive type 2 on my HTC phone - L OS (sometimes for incoming message too I see type==2).
How can I separate this onChange request, as I am particularly looking for SMS SENT change.
Related
I have developed a voice calling app with android ConnectionServices and telecom framework.
I can show native call screen when receive incoming call notification from firebase and everything is fine.
When I start an outgoing call I just want to report this call to Connection service so that if any call from gsm received it should report busy to caller. In callkit if you call reporting Outgoing call native callkit screen doesnt appears on my app screen but android shows native call.
is it possible to make native screen invisible for outgoing calls?
my function to report outgoing call is below;
public void startCall(String number, String uuidString) {
UUID uuid = null;
if (uuidString != null) {
uuid = UUID.fromString(uuidString);
}
//TODO: allow name passed in as well
Log.d(TAG, "startCall number: $number");
Bundle extras = new Bundle();
Uri uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null);
Bundle callExtras = new Bundle();
callExtras.putString(Constants.EXTRA_CALL_NUMBER, number);
if (uuid != null) {
callExtras.putString(Constants.EXTRA_CALL_UUID, uuid.toString());
}
extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, voipUtilties.handle);
extras.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, callExtras);
if (ActivityCompat.checkSelfPermission(Application.context, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
Log.d("VOIP_pLuGIN", "Yetki Yok");
return;
}else{
voipUtilties.telecomManager.placeCall(uri, extras);
}
}
and overrided outgoingConnection in Service class is like below.
#Override
public Connection onCreateOutgoingConnection(PhoneAccountHandle
connectionManagerPhoneAccount, ConnectionRequest request) {
Bundle extras = request.getExtras();
Connection outgoingCallConnection = null;
String number = request.getAddress().getSchemeSpecificPart();
String extrasNumber = extras.getString(EXTRA_CALL_NUMBER);
String displayName = extras.getString(EXTRA_CALLER_NAME);
boolean isForeground = VoipConnectionService.isRunning(this.getApplicationContext());
Log.d(TAG, "makeOutgoingCall:, number: " + number + ", displayName:" + displayName);
// Wakeup application if needed
if (!isForeground) {
Log.d(TAG, "onCreateOutgoingConnection: Waking up application");
//TODO:
}
outgoingCallConnection = createConnection(request);
outgoingCallConnection.setDialing();
outgoingCallConnection.setAudioModeIsVoip(true);
outgoingCallConnection.setCallerDisplayName(displayName, TelecomManager.PRESENTATION_ALLOWED);
// ️Weirdly on some Samsung phones (A50, S9...) using `setInitialized` will not display the native UI ...
// when making a call from the native Phone application. The call will still be displayed correctly without it.
if (!Build.MANUFACTURER.equalsIgnoreCase("Samsung")) {
outgoingCallConnection.setInitialized();
}
Log.d(TAG, "onCreateOutgoingConnection: calling");
final String uuid = outgoingCallConnection.getExtras().getString(EXTRA_CALL_UUID);
setAllOthersOnHold(uuid);
final String address = outgoingCallConnection.getExtras().getString(EXTRA_CALL_NUMBER);
Log.d(TAG,"Created call's uuid" + uuid);
return outgoingCallConnection;
}
any idea will be appriciated.
I was using this package for my project. In VoipUtilities.kt Changing PhoneAccount capability to CAPABILITY_SELF_MANAGED instead of CAPABILITY_CALL_PROVIDER and in VoipconnectionService.java I added this code chunk to createConnection function solved my problem.
if((phoneAccount.getCapabilities() & PhoneAccount.CAPABILITY_SELF_MANAGED) == PhoneAccount.CAPABILITY_SELF_MANAGED) {
Log.d(TAG, "[VoiceConnectionService] PhoneAccount is SELF_MANAGED, so connection will be too");
connection.setConnectionProperties(Connection.PROPERTY_SELF_MANAGED);
}
I would like to monitor/filter the websites that an user opens in Android.
I know how to retrieve the last visited URL (in Android default browser) using a ContentObserver on the browser history...
private static class BrowserObserver extends ContentObserver {
private static String lastVisitedURL = "";
private static String lastVisitedWebsite = "";
//Query values:
final String[] projection = new String[] { Browser.BookmarkColumns.URL }; // URLs
final String selection = Browser.BookmarkColumns.BOOKMARK + " = 0"; // history item
final String sortOrder = Browser.BookmarkColumns.DATE; // the date the item was last visited
public BrowserObserver(Handler handler) {
super(handler);
}
#Override
public void onChange(boolean selfChange) {
onChange(selfChange, null);
}
#Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange);
//Retrieve all the visited URLs:
final Cursor cursor = getContentResolver().query(Browser.BOOKMARKS_URI, projection, selection, null, sortOrder);
//Retrieve the last URL:
cursor.moveToLast();
final String url = cursor.getString(cursor.getColumnIndex(projection[0]));
//Close the cursor:
cursor.close();
if ( !url.equals(lastVisitedURL) ) { // to avoid information retrieval and/or refreshing...
lastVisitedURL = url;
//Debug:
Log.d(TAG, "URL Visited: " + url + "\n");
}
}
}
To register the ContentObserver I use:
browserObserver = new BrowserObserver(new Handler());
getContentResolver().registerContentObserver(Browser.BOOKMARKS_URI, true, browserObserver);
And to unregister it:
getContentResolver().unregisterContentObserver(browserObserver);
This works. However, in this way, I can analyze the URLs only after the browser has loaded them.
Now, is there a way to retrieve the URLs before the browser actually loads them in Android?
A solution which could help to create a Web Monitor, is to creation your own VPN service, so that you monitor all the device traffic. A good example of this is the project NetGuard.
https://github.com/M66B/NetGuard
Note that in some devices, the system will not pass through the VPN some applications (ex, in Samsung devices, the Samsung Web Browser is not forwarded through the system VPN, checked in S5 with Android 6.0).
Also your application should request the permission to be used as a VPN Service, but once the user gives this permission, it can monitor and filter most of the device network traffic.
I was looking quite a bit on the forums for determining how many SMS messages I have that were not read. The code below seems to work good for received messages, but once I actually read the message the onChange of the ContentObserver is not being called.
So, on incoming SMS message the onChange is getting called and I get the correct number, but after reading the message it is not being called. The device is Samsung Note running Android 2.3.6 not rooted. Any help will be appreciated.
public class UnreadSMSContentObserver extends ContentObserver {
private static final String myTAG="PhoneInfoSMS";
private static final Uri SMS_INBOX = Uri.parse("content://sms/inbox");
private ContentResolver mContentResolver;
private Handler mHandler;
public int unreadSMS;
private static final String TAG = "PhoneInfoSMS";
public UnreadSMSContentObserver(ContentResolver cr, Handler h) {
super(null);
mContentResolver = cr;
mHandler = h;
}
public int getUnreadSMS() {
if (mContentResolver != null) {
try {
Cursor c = mContentResolver.query(SMS_INBOX, null, "read = 0", null, null);
if (c != null) {
unreadSMS = c.getCount();
c.deactivate();
Log.d(TAG, unreadSMS + " unread SMS messages");
}
}
catch (Exception ex) {
Log.e("ERROR: " + ex.toString(), "");
}
}
return unreadSMS;
}
#Override
public void onChange(boolean selfChange) {
Log.d(myTAG, "onChange");
if (mContentResolver != null) {
getUnreadSMS();
mHandler.obtainMessage(PhoneInfoServer.CONTENTO_INFOCHANGED, PhoneInfoServer.CONTENTO_US, unreadSMS).sendToTarget();
Log.d(myTAG, "done");
}
}
}
In the manifest file I have the following permissions:
"android.permission.READ_CONTACTS"
"android.permission.READ_SMS"
"android.permission.GET_ACCOUNTS"
"android.permission.BATTERY_STATS"
"android.permission.BLUETOOTH"
"android.permission.BLUETOOTH_ADMIN"
"android.permission.BROADCAST_SMS"
"android.permission.RECEIVE_SMS"
"android.permission.BROADCAST_SMS"
"android.permission.RECEIVE_MMS"
The way I set it up on the calling service is:
in the onCreate of the service I do:
mContentResolver = this.getContentResolver();
mUnreadSMSContentObserver = new UnreadSMSContentObserver(mContentResolver, mContentObserversHandler);
in the onStartCommand of the service I do:
mContentResolver.registerContentObserver(Uri.parse("content://sms/"), true, mUnreadSMSContentObserver);
mContentResolver.registerContentObserver(Uri.parse("content://sms/inbox/"), true, mUnreadSMSContentObserver);
I tried only the content://sms/ and only content://sms/inbox/ and both... did not solve the problem.
P.S. Similar method for the missed calls works perfect!
The application+service is sending over Bluetooth the battery data, missed calls and unread SMS messages to an Arduino based device that displays it on an LED screen. Why? Two reasons: first, this is my first Android program made for fun. The second is I am not carrying the phone with me at home all the time, and it is typically in my home office. If I did not hear it ringing I will still be able to see the LED display telling me I had calls or SMS when passing by.
this solution has worked for me :
context.getContentResolver().
registerContentObserver(Uri.parse("content://mms-sms/"), true, smsObserver);
I am trying to send MMS programatically by using the post How to send image via MMS in Android? ....
I am trying to retrieve the APN values MMSC, MMSProxy and MMSPort , but I am getting empty values for the MMSProxy and MMSPort.. then I checked for these values in my HTC device by navigating "Settings-->Wireless&Networks-->MobileNetworks-->AccessPointNames-->MMS-->"
but here actually nothing is was set for MMSProxy and MMSPort....
but I am able to send MMS manually..
Please help me in how to get MMSProxy and MMSPort values.. or plz tell me if built-in MMS application will use any other mechanism to send MMS..??
plz help me in this...
It might not matter, proxy can mean an "alternate" route. maybe sending MMS doesn't need an alternate route so it's null?
the built in MMS app uses a class called TransactionSettings.java and that class queries the Telephony content provider, code excerpt.
public TransactionSettings(Context context, String apnName) {
String selection = (apnName != null) ? APN + "='" + apnName.trim() + "'" : null;
Cursor cursor = SqliteWrapper.query(context, context.getContentResolver(), Uri.withAppendedPath(Uri.parse(TELEPHONY_CONTENT_URI), "current"),
APN_PROJECTION, selection, null, null);
if (cursor == null) {
Log.e(TAG, "Apn is not found in Database!");
return;
}
boolean sawValidApn = false;
try {
while (cursor.moveToNext() && TextUtils.isEmpty(mServiceCenter)) {
// Read values from APN settings
if (isValidApnType(cursor.getString(COLUMN_TYPE), APN_TYPE_MMS)) {
sawValidApn = true;
mServiceCenter = cursor.getString(COLUMN_MMSC).trim();
mProxyAddress = cursor.getString(COLUMN_MMSPROXY);
if (isProxySet()) {
String portString = cursor.getString(COLUMN_MMSPORT);
try {
mProxyPort = Integer.parseInt(portString);
} catch (NumberFormatException e) {
if (TextUtils.isEmpty(portString)) {
Log.w(TAG, "mms port not set!");
} else {
Log.e(TAG, "Bad port number format: " + portString, e);
}
}
}
}
}
} finally {
cursor.close();
}
That being said, I use this method and still get null values.
Maybe you had better luck?
Is it possible to intercept outgoing emails from Android? I have tried with content provider by using ContentObserver but still no luck.
this is my code.
final String AUTHORITY_PLUS_MESSAGES = "content://gmail-ls/messages/";
String[] gmailAccounts = getGmailAccount(this.getApplicationContext());
String firstEmailAddress = gmailAccounts[0];
Handler handler = new Handler();
ContentResolver resolver = getContentResolver();
ContentObserver observer = new GmailObserver(handler, resolver, firstEmailAddress);
Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + firstEmailAddress + "/");
resolver.registerContentObserver(uri, Boolean.TRUE, observer);
class GmailObserver extends ContentObserver {
public void onChange(final boolean bSelfChange) {
super.onChange(bSelfChange);
Log.d(TAG, "***** onChange");
// here I am getting lots of calls but not sure how to deal with outgoing messages ..
}
}
Is it possible to intercept outgoing emails from Android?
No, sorry.