Can I still delete sms from android inbox in the latest version? - android

I want to delete sms from android inbox when I receive it in my app. I already researched stackoverflow and found the codes but it doesn't work. I am not sure this is because I am using the latest android, gradle and emulator.
private fun deleteSMS(message: String, number: String): Boolean {
try {
Log.d(TAG, "Deleting SMS from inbox")
val uri = Uri.parse("content://sms/inbox")
val c = this.contentResolver.query(uri, null, null, null, null)
c?.let {
if(!it.moveToFirst()) {
it.close()
return false
}
do {
val id = it.getInt(0)
val threadId = it.getInt(1)
val address = it.getString(2)
val body = it.getString(5)
Log.d(TAG, "address, body: $address : $body")
this.contentResolver.delete(Uri.parse("content://sms/$id"), null, null)
}while (it.moveToNext())
}
c?.close()
return true
}catch (e: Exception) {
Log.e(TAG, e.message)
return false
}
}
I tried this code in java but it also doesn't work. Anyone can help me?

Unfortunately, deleting SMS messages like that is no longer possible since Android 4.4 (KitKat), unless your app is the default SMS app or the device is rooted.
Also, the system now allows only the default app to write message data to the provider, although other apps can read at any time.
http://developer.android.com/about/versions/kitkat.html
If you try anyway, it silently fails - it won't delete anything, won't raise any exceptions and won't display error messages.
If you only intend to target 4.4 in your app, then this workaround might help, but it won't work in later versions.

Related

How to open Google Play from the phone remotely on the watch (Wear OS)

What is the correct way to remotely open Google Play from the phone on the watch (Wear OS)? I am trying this:
Intent intentOnWatch = new Intent(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.parse("https://play.google.com/store/apps/details?id=\" + getPackageName()"));
RemoteIntent.startRemoteActivity(getApplicationContext(), intentOnWatch, null, null);
But nothing happens.
The last parameter is the nodeId. I left it as zero because the documentation says :
nodeId String: Wear OS node id for the device where the activity should be started. If null, and the current device is a watch, the activity will start on the companion phone device. Otherwise, the activity will start on all connected watch devices.
Source: https://developer.android.com/reference/com/google/android/wearable/intent/RemoteIntent#startremoteactivity
I could determine the nodeId, but it seems difficult to do. Plus in this case, starting the activity on all connected watch devices would be fine.
Is it possible to download a file using DownloadManager?
This example (sorry it's Kotlin) should work
val remoteActivityHelper =
RemoteActivityHelper(application, Dispatchers.IO.asExecutor())
val nodes = Wearable.getNodeClient(application).connectedNodes.await()
val nodeId = nodes.firstOrNull { it.displayName == "XXX" }?.id
if (nodeId == null) {
Toast.makeText(application, "No connected wear watch", Toast.LENGTH_SHORT).show()
} else {
try {
remoteActivityHelper.startRemoteActivity(
Intent(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(
Uri.parse("https://www.bbc.co.uk/sounds/play/${programme.code}")
),
).await()
} catch (e: Exception) {
toaster.showToast("Unable to open mobile app: ${e.message}")
}
}
}
But the main thing in your example is that you are not checking the result of startRemoteActivity, it returns a ListenableFuture, so you could check for an error. In the example above, I'm using the .await() extension function which does the same thing.
There are more complete examples in https://github.com/android/wear-os-samples/blob/d18c489ff415aa0fbb25c260e3aacdf50f7716e3/WearVerifyRemoteApp/Application/src/main/java/com/example/android/wearable/wear/wearverifyremoteapp/MainMobileActivity.kt
I'm not sure about the exact implementation for Java, it's really messy with the Task and Future APIs mixed here. Maybe
RemoteActivityHelper remoteActivityHelper = new RemoteActivityHelper(application, executor);
NodeClient client = Wearable.getNodeClient(application);
client.getConnectedNodes().addOnSuccessListener(nodes -> {
if (nodes.size() > 0) {
String nodeId = nodes.get(0).getId();
ListenableFuture<Void> result = remoteActivityHelper.startRemoteActivity(
new Intent(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(
Uri.parse("https://www.bbc.co.uk/sounds/play/${programme.code}")
)
, nodeId);
result.addListener(() -> {
try {
result.get();
} catch (Exception e) {
Toast.makeText(application, "Failed " + e, Toast.LENGTH_SHORT).show();
}
}, executor);
} else {
Toast.makeText(application, "No connected wear watch", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(failure -> {
Toast.makeText(application, "Unable to open mobile app: ${e.message}", Toast.LENGTH_SHORT).show();
});
I've been fighting with exatly the same problem last two days.
Works for me the next code:
Intent intent = new Intent(Intent.ACTION_VIEW)
.addCategory(Intent.CATEGORY_BROWSABLE)
.setData(Uri.parse(PLAY_STORE_APP_URI));
for (Node node : nodesWithoutApp) {
RemoteActivityHelper remoteActivityHelper =
new RemoteActivityHelper(this, Executors.newSingleThreadExecutor());
remoteActivityHelper.startRemoteActivity(intent, node.getId());
}
It didn't work with RemoteIntent.startRemoteActivity for some reason.

“Error getting Mms Carrier values” when querying Android Telephony.Carriers public class

I am having trouble obtaining the "server", "mms_proxy", and "mms_port". I haven't found anything official anywhere from Google about why this is? I would assume if this is something I cannot do then that would be stated by Google.
The Android developer website shows the Telephony.Carriers class and all that is available but says nothing about restrictions of any kind so at this point I believe it is fair to assume I can access these rather than have to ask the user to find the APN values manually which will make many people give up instantly and not use my App.
Can we please try to find an official answer as to what is going on here, I have attempted to get this information in many ways all leading to very confusing errors that seemingly cannot be explained.
I am running Android 6.01 on the device ZTE Axon 7. The lowest api that my App will allow is api_21 and the Telephony.Carriers class in available from api_19 and up.
I have declared all then necessary permission in the Manifest file and since I am currently testing on sdk "M" (Android 6), I have also acquired the permissions explicitly at Runtime from the user.
This is the code inside my Activity that I run and receive a an error stating "Error getting Mms Carrier values"...this is the whole problem and where I have become stuck.
ContentResolver contentResolver = getContentResolver();
int index_ID;
final String[] PROJECT =
{
Telephony.Carriers.TYPE,
Telephony.Carriers.MMSC,
Telephony.Carriers.MMSPROXY,
Telephony.Carriers.MMSPORT,
};
grantMyUriPermission(activity, Telephony.Carriers.CONTENT_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
grantMyUriPermission(activity, Telephony.Carriers.CONTENT_URI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Cursor carriers_cursor = SqliteWrapper.query(activity, contentResolver,
Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"), PROJECT, null, null, null);
if (carriers_cursor != null)
{
/*This crap below isn't needed for this situation but helps avoid ERROR*/
index_ID = carriers_cursor.getColumnIndex(Telephony.Carriers._ID);
//--------------------------------------------------------------------------------------
if (index_ID < 0 || !carriers_cursor.moveToFirst())
{
Log.i(TAG, "Error getting Mms Carrier values");
carriers_cursor.close();
return;
}
//--------------------------------------------------------------------------------------
do
{
//Confirm cursor has value assigned to it
Log.i(TAG, "cursor: "+ carriers_cursor);
//Get the available columns names
for (String item : carriers_cursor.getColumnNames())
{
//Name of each column available with Cursor
Log.i(TAG, "item: " + item);
//Attempt to get String value for each available column
try
{
//Use the name of the column, to get the index, to get the String value
Log.i(TAG, "getString(): " + carriers_cursor.getString(carriers_cursor.getColumnIndex(item)));
}
catch (Exception e)
{
Log.i(TAG, "Exception: " + e);
}
}
}
while (carriers_cursor.moveToNext());
carriers_cursor.close();
}
The Log output is:
I/SmsReceiveIntentService: Running grantMyUriPermission()
I/SmsReceiveIntentService: Running grantMyUriPermission()
I/NewConversationActivity: Error getting Mms Carrier values
And that's it! Nothing else to go on...?

How to check if firebase service is available?

In cases when the app is running behind a firewall or there is a network outage or some sort of censorship, How can we check using code to see if the app can access the firebase systems?
You should check if Google Play Service is available like this:
/**
* Check the device to make sure it has the Google Play Services APK. If it
* doesn't, display a dialog that allows users to download the APK from the
* Google Play Store or enable it in the device's system settings.
*/
public static boolean checkPlayServices(Context context) {
int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable
(context);
if (resultCode != ConnectionResult.SUCCESS) {
Log.i(TAG, "This device does not support Google Play Services. " +
"Push notifications are not supported");
return false;
}
return true;
}
You need to add the following line to your build.gradle also.
compile 'com.google.android.gms:play-services-gcm:11.8.0'
I am guessing currently there is no way you can check whether Firebase is available or not from codes inside the app. However you can check if Firebase itself is working fine by checking Firebase Status Dashboard.
In this site you can also find in what date Firebase service was not available or unstable in the past.
Hope it helps in some way.
https://status.firebase.google.com/
As the
FirebaseApp.getInstance() throws IllegalStateException
you my try below solution
private val isFirebaseEnabled: Boolean
get() {
return try {
FirebaseApp.getInstance() != null. //that is always true, nevertheless it will throw exception if Firebase is not available
} catch (e: IllegalStateException) {
false
}
}
unfortunately it won't check actual network restrictions. You may try to ping FCM and catch connection timeout. E.g.
private fun isInternetAvailable(): Boolean {
return try {
val connection = URL("https://theUrl.com").openConnection() as HttpURLConnection
connection.setRequestProperty("User-Agent", "Test")
connection.connectTimeout = 10000
connection.connect()
connection.disconnect()
true
} catch (e: Exception) {
false
}
}

GSF ID KEY (google service framework id) as Android device unique identifier

I need to uniquely identify an Android device. I read about ANDROID_ID but it seems to have problems with Android 2.2. Then there are other identifiers related to TelephonyManager, but I reckon they don't work on tablets.
So, looking for something working on every device I stumbled upon the GSF ID KEY (google service framework id). Do you guys think this is a reliable and always working solution?
This is the code I found to retrieve the GSF ID KEY:
private static String getGsfAndroidId(Context context)
{
Uri URI = Uri.parse("content://com.google.android.gsf.gservices");
String ID_KEY = "android_id";
String params[] = {ID_KEY};
Cursor c = context.getContentResolver().query(URI, null, null, params, null);
if (!c.moveToFirst() || c.getColumnCount() < 2)
return null;
try
{
return Long.toHexString(Long.parseLong(c.getString(1)));
}
catch (NumberFormatException e)
{
return null;
}
}
In case someone is wondering if this method works the answer is yes, I tried it (and used it in an app I put on the Android market with thousands of downloads) and it works. Note: the GSF ID KEY changes every time the user does a factory reset or messes up with Google Services, but it was good enough for my purpose.
using Android Studio, I get auto-recommendations from lint. here is the code, after revised. it may solve exceptions reported by https://stackoverflow.com/users/423171/cprcrack
private static String getGsfAndroidId(Context context)
{
Uri URI = Uri.parse("content://com.google.android.gsf.gservices");
String ID_KEY = "android_id";
String params[] = {ID_KEY};
Cursor c = context.getContentResolver().query(URI, null, null, params, null);
if (c != null && (!c.moveToFirst() || c.getColumnCount() < 2)){
if(!c.isClosed())
c.close();
return null;
}
try {
if (c != null) {
String result = Long.toHexString(Long.parseLong(c.getString(1)));
if(!c.isClosed())
c.close();
return result;
}else {
return null;
}
} catch (NumberFormatException e) {
if(!c.isClosed())
c.close();
return null;
}
}
Can't talk about production tests, but I noticed that in my Nexus 5 with Android 5.0, I had to add the following permission: com.google.android.providers.gsf.permission.READ_GSERVICES. Otherwise an exception is raised when using your code.
Can't talk about production tests, but I noticed that in my Nexus 5 with Android 5.0, I had to add the following permission: com.google.android.providers.gsf.permission.READ_GSERVICES. Otherwise an exception is raised when using your code.
Share Improve this answ

read mails in my own android app

I have do an android application, and now, this application needs to read emails. I found this code:
protected ArrayList<Mail> doInBackground(Void... params) {
ArrayList<Mail> mails = new ArrayList<Mail>(32);
boolean finish = false;
try {
String direcCompleta = URI_PREFIX + email;
Uri a = Uri.parse(direcCompleta);
Cursor cCursor = resolver.query(a, null, null , null, null);
while (cCursor.moveToNext() && (! finish)) {
finish = fromTime.before(new Date(cCursor.getLong(1)));
if (! finish){
String conv_id = cCursor.getString(cCursor.getColumnIndex("_id"));
Uri uri = Uri.parse(URI_PREFIX + email + "/" + conv_id + "/messages");
Cursor mCursor = resolver.query(uri, MESSAGE_PROJECTION, null, null, null);
while (mCursor.moveToNext() && (! finish)){
long mtime = mCursor.getLong(4);
finish = fromTime.before(new Date(mtime));
if (! finish){
mails.add(new Mail(mCursor.getString(0), mCursor.getString(2), mCursor.getString(1), mCursor.getString(4), mtime));
}
}
}
}
} catch (Exception ex){
Log.e("GmailReadApp", ex.toString());
mails.add(new Mail(null, null, ex.toString(), ex.toString(), 0));
}
return mails;
}
But cCursor is null. I have my mail account in app: "Email", because i work with android sdk, and it doesn´t have app: "GMAIL". And android sdk doesn´t have market.
Somebody can help me please? thanks. (no matter if it's for gmail, yahoo, hotmail,....)
I have do an android application, and now, this application needs to read emails
Write your own email client from scratch, then. There is an Android port of JavaMail floating around somewhere. Or, grab an existing open source email client (e.g., K9) and modify it to suit.
I found this code
There is no possible value of URI_PREFIX that is documented and supported for use on Android. Even for the undocumented and unsupported values, you cannot hold the permissions necessary to read those messages.
You can do it with Kotlin.
Download jar files: additionnal.jar, mail.jar, activation.jar
Add those jars in External Libraries in android studio
Add internet permission in manifest file:
<uses-permission android:name="android.permission.INTERNET" />
Enable less secure apps to access your Gmail
Add this code to your app:
GlobalScope.launch {
val props = Properties()
props.setProperty("mail.store.protocol", "imaps")
try{
val session = Session.getInstance(props, null)
val store = session.store
store.connect("imap.gmail.com", "youremail#gmail.com", "password")
val inbox = store.getFolder("INBOX")
inbox.open(Folder.READ_ONLY)
Log.d("MyLog", inbox.messageCount.toString())
val msg = inbox.getMessage(inbox.messageCount)
val address = msg.from
for (adr in address) {
Log.d("MyLog", adr.toString())
}
val mp = msg.content as Multipart
val bp = mp.getBodyPart(0)
Log.d("MyLog", bp.content.toString())
}catch (e: Exception){
Log.d("MyLog", "Error $e")
}
}

Categories

Resources