Android MMS observer - android

I have the following code:
public class MmsObserver extends ContentObserver {
private Context context;
public MmsObserver(Handler handler) {
super(handler);
this.context = service.getBaseContext();
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Long largestDateCounted = Long.parseLong(UserPreferencesManager.getInstance().getValueFromPreferences(context, context.getString(R.string.preferences_current_counter), "0"));
String filter = "creator != ? and date > ?";
String[] args = new String[]{context.getPackageName(), Long.toString(largestDateCounted)};
Cursor c = context.getContentResolver().query(Constants.Mms, null, filter, args, null);
try {
} catch (Exception e) {
e.printStackTrace();
} finally {
c.close();
}
}
}
I'm trying to observe when user sends/receives an MMS message. However, my observer never gets called. Is there something I'm missing on this? I have read the below:
Android MMS Monitoring
Android MMS Broadcast receiver
EDIT
here is how i'm running the observer:
mmsContent = new MmsObserver(new Handler());
getContentResolver().registerContentObserver(Constants.Mms, true, mmsContent);

When registering a ContentObserver for MMS, the URI needs to be content://mms-sms/, at least on older Android versions. For some reason, content://mms/ won't work for a ContentObserver, other than possibly firing on changes to draft messages.
Do note that this will cause the Observer to fire for changes to the SMS table, as well.

Related

Linphone core listener not receiving incoming calls

I was trying to add sip incoming calls with linphone sdk, The registration is successful and I can make out going calls and the call status is logging as expected, but I am not able to receive incoming calls. I am using intent service to handle connection.
Here is my code:
protected void onHandleIntent(Intent intent) {
String sipAddress = intent.getStringExtra("address");
String password = intent.getStringExtra("password");
final LinphoneCoreFactory lcFactory = LinphoneCoreFactory.instance();
// First instantiate the core Linphone object given only a listener.
// The listener will react to events in Linphone core.
try {
lc = lcFactory.createLinphoneCore(new LinphoneCoreListenerBase() {
#Override
public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) {
super.callState(lc, call, state, message);
Log.i(TAG, "callState: ");
}
}, getApplication());
} catch (LinphoneCoreException e) {
e.printStackTrace();
}
lc.setUserAgent("Test app", "1.0");
try {
LinphoneAddress address = lcFactory.createLinphoneAddress(sipAddress);
String username = address.getUserName();
String domain = address.getDomain();
if (password != null) {
lc.addAuthInfo(lcFactory.createAuthInfo(username, password, null, domain));
}
// create proxy config
LinphoneProxyConfig proxyCfg = lc.createProxyConfig(sipAddress, domain, null, true);
proxyCfg.setExpires(2000);
lc.addProxyConfig(proxyCfg); // add it to linphone
lc.setDefaultProxyConfig(proxyCfg);
running = true;
while (running) {
lc.iterate(); // first iterate initiates registration
sleep(20);
}
} catch (LinphoneCoreException e) {
e.printStackTrace();
}
}
What is wrong with my code?
As the IntentService document (https://developer.android.com/reference/android/app/IntentService) stated:
the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
I think you should not put the listener in an IntentService. Instead, put it in a long running Service so that the listener can actually keep staying there to receive events.

Speech recognition supported languages on Android

I'm having a problem getting the supported languages. I have seen a solution
that is to create a Broadcast receiver and fill the list with the languages.
public class LanguageChecker extends BroadcastReceiver
{
private List<String> supportedLanguages;
private String languagePreference;
#Override
public void onReceive(Context context, Intent intent)
{
//Log.d(Constants.Tag,"OnReceive");
Bundle results = getResultExtras(true);
if (results.containsKey(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE))
{
languagePreference =
results.getString(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE);
}
if (results.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES))
{
supportedLanguages =
results.getStringArrayList(
RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);
}
}
public List<String> getSupportedLanguages() {
return supportedLanguages;
}
}
but the problem is that I need this supportedLanguages list to fill my spinner.
When I call the method getSupportedLanguages, I get null.
This is how I use the broadcast within onCreate:
try {
lang = new LanguageChecker();
Intent detailsIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);
sendOrderedBroadcast(detailsIntent, null, lang, null, Activity.RESULT_OK, null, null);
supportedLanguagesForSpeech=lang.getSupportedLanguages();
Log.d(Constants.Tag, String.valueOf(supportedLanguagesForSpeech.size()));
}
catch (Exception e){
Log.d(Constants.Tag,e.getMessage());
}
You should solve it with a callback to make sure that supportedLanguages is assigned. You are getting null because you are not waiting onReceive to be called.
Here is my current solution to querying all the available speech recognition services for their supported languages:
https://github.com/Kaljurand/K6nele/blob/3e514edc87e07babb0be57fa31ab48be7e2226e7/app/src/ee/ioc/phon/android/speak/RecognitionServiceManager.java
You can see it in action in the Kõnele app (http://kaljurand.github.io/K6nele/about/), in the "Settings -> Recognition languages & services" list.

Monitor Android system settings values

I want to watch a system setting and get notified when its value changes. The Cursor class has a setNotificationUri method which sounded nice, but it doesn't work and coding it also feels strange... Thats what I did:
// Create a content resolver and add a listener
ContentResolver resolver = getContentResolver();
resolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS | ContentResolver.SYNC_OBSERVER_TYPE_PENDING | ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE, new MyObserver());
// I somehow need to get an instance of Cursor to use setNotificationUri in the next step...
Cursor cursor2 = resolver.query(Settings.System.CONTENT_URI, null, null, null, null);
// For testing purposes monitor all system settings
cursor2.setNotificationUri(resolver, Settings.System.CONTENT_URI);
The listener:
public class MyObserver implements SyncStatusObserver {
public void onStatusChanged(int which) {
Log.d("TEST", "status changed, which = " + which);
}
}
Well, obviously the listener gets never called, I can't find an entry with the specified TEST tag in logcat ): (For testing I manually changed the brightness setting from manual to automatic in the android settings menu). Any hint what I am doing wrong? Any other, better way to monitor Android system settings?
Thanks for any hint!
Here's some example code:
ContentResolver contentResolver = getContentResolver();
Uri setting = Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION);
// Make a listener
ContentObserver observer = new ContentObserver(new Handler()) {
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
}
#Override
public boolean deliverSelfNotifications() {
return true;
}
};
// Start listening
contentResolver.registerContentObserver(setting, false, observer);
// Stop listening
contentResolver.unregisterContentObserver(observer);
Check out the documentation for any of these methods for more details.
here is how it can be done, works great: How to implement a ContentObserver for call logs. note than some settings are first written / reallly changed when the user presses the back key in the system preference screen where he changed something!

How to suspend notification to observers while doing many changes using a ContentProvider

I have an ExpandableListView that uses a SimpleCursorTreeAdapter which uses the cursors returned by a ContentProvider. This is fine as it always keeps in sync with the data but sometimes I need to do many changes to the database so that the cursor is requeried many times in the same second. Is it possible to suspend the notification of ContentObservers to avoid unnecessary requerys?
A possible solution is to modify the content provider to allow suspending notifications. URIs to be notified are added to a queue until suspension is disabled.
private boolean suspendNotifications = false;
private LinkedList<Uri> suspendedNotifications = new LinkedList<Uri>();
private HashSet<Uri> suspendedNotificationsSet = new HashSet<Uri>();
private void notifyChange(Uri uri) {
if (suspendNotifications) {
synchronized (suspendedNotificationsSet) { // Must be thread-safe
if (suspendedNotificationsSet.contains(uri)) {
// In case the URI is in the queue already, move it to the end.
// This could lead to side effects because the order is changed
// but we also reduce the number of outstanding notifications.
suspendedNotifications.remove(uri);
}
suspendedNotifications.add(uri);
suspendedNotificationsSet.add(uri);
}
}
else {
getContext().getContentResolver().notifyChange(uri, null);
}
}
private void notifyOutstandingChanges() {
Uri uri;
while ((uri = suspendedNotifications.poll()) != null) {
getContext().getContentResolver().notifyChange(uri, null);
suspendedNotificationsSet.remove(uri);
}
}
private void setNotificationsSuspended(boolean suspended) {
this.suspendNotifications = suspended;
if (!suspended) notifyOutstandingChanges();
}
#Override
public Uri insert(Uri uri, ContentValues values) {
...
notifyChange(uri);
return newItemUri;
}
I'm not sure how to best enable/disable suspension but one possibility would be to have a special URI which turns on/off suspension (e.g. content://<authority>/suspension) in the update() method:
#Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
switch (uriMatcher.match(uri)) {
...
case SUSPEND:
boolean enabled = values.getAsBoolean("enabled");
setNotificationsSuspended(enabled);
break;
...
}
}
The service that does the changes to the database can now suspend the ContentProvider when it starts and disable suspension when it finishes.
Can you use http://developer.android.com/reference/android/widget/BaseAdapter.html#unregisterDataSetObserver(android.database.DataSetObserver) to unRegister your listeners and once your work is ready, register them again? Sounds like a AsyncTask to me.

Detecting new MMS (Android 2.1)

I'd like to recognize arrival of new MMS msg (after it is downloaded to inbox). I am doing the following:
private MMSContentObserver mMmsCO;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
h = new Handler();
mMmsCO = new MMSContentObserver(h);
getContentResolver().registerContentObserver (Uri.parse("content://mms"), true, mMmsCO);
}
where
private class MMSContentObserver extends ContentObserver {
public MMSContentObserver(Handler h) {
super(h);
}
#Override
public boolean deliverSelfNotifications() {
return false;
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
}
}
However, onChange is not getting called. What am I missing?
Thanks in advance.
The MMS content provider isn't part of the SDK but it can be used... a real answer here would be nice since all messaging apps use content://mms in some way or shape.
Since google decided not to standardize MMS we are all have to test on every phone out there but we still need to be able to handle MMSs in our apps.

Categories

Resources