TelephonyManager getSubscriberId() and getSimSerialNumber() return null in android Q!
I'm coding in java with android studio IDE!
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.getSimSerialNumber(); //it is null
If your apk's targetsdk <30, you can get ICCID by the following method without any permission even in android 11.
Uri uri = Uri.parse("content://telephony/siminfo");
Cursor cursor = null;
ContentResolver contentResolver = getApplicationContext().getContentResolver();
cursor = contentResolver.query(uri,
new String[]{"_id", "sim_id", "imsi","icc_id","number","display_name"}, "0=0",
new String[]{}, null);
if (null != cursor) {
while (cursor.moveToNext()) {
String icc_id = cursor.getString(cursor.getColumnIndex("icc_id"));
String imsi_id = cursor.getString(cursor.getColumnIndex("imsi"));
String phone_num = cursor.getString(cursor.getColumnIndex("number"));
String display_name = cursor.getString(cursor.getColumnIndex("display_name"));
int sim_id = cursor.getInt(cursor.getColumnIndex("sim_id"));
int _id = cursor.getInt(cursor.getColumnIndex("_id"));
Log.d("Q_M", "icc_id-->" + icc_id);
Log.d("Q_M", "imsi_id-->" + imsi_id);
Log.d("Q_M", "phone_num-->" + phone_num);
Log.d("Q_M", "sim_id-->" + sim_id);
Log.d("Q_M", "display_name-->" + display_name);
}
}
public String getSimSerialNumber ()
Returns the serial number of the SIM, if applicable. Return null if it is unavailable.
Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or profile owner and have the READ_PHONE_STATE permission.
See the following link:
getSerialNumber()
Also if are your app is can be selectable as default SMS app you can get this data without need any permissions.
For set your app as the default SMS app please look that page
Related
Hey so I just made an android app which basically fetches all the mp3/wav files from your phone and then shows them it to you. Which you can then play them. But I am experiencing slow load times. My phone has like 10 mp3 and its a 6GB RAM phone. But it takes like 1 minute to load all those files. I am using the built in MediaPlayer Class. Any tips?
Use this code.
for reference link
public void getMp3Songs() {
Uri allsongsuri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + " != 0";
songsList.clear();
Cursor cursor = managedQuery(allsongsuri, null, selection, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
String song_name = cursor
.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
int song_id = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media._ID));
String fullpath = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.DATA));
songsList.add(fullpath);
String album_name = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM));
int album_id = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
String artist_name = cursor.getString(cursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST));
int artist_id = cursor.getInt(cursor
.getColumnIndex(MediaStore.Audio.Media.ARTIST_ID));
} while (cursor.moveToNext());
}
cursor.close();
}
Toast.makeText(context, ""+songsList.size(), Toast.LENGTH_SHORT).show();
}
Here, this renameFile(..) func is working in Android API 30. But, it is not working in Android API 29 and shows the error like :
java.lang.IllegalArgumentException: Movement of content://media/external/file/116 which isn't part of well-defined collection not allowed
Update-Note:
---Begins---
In-order to work with sdk-29 we have to use Uri as extUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL) like:
private static Uri extUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL);
in place of below code. And also update MediaStore.Files.FileColumns to MediaStore.Downloads
---Ends---
Uri extUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
String relativeLocation = Environment.DIRECTORY_DOWNLOADS + File.separator + "AppFolder";
function renameFile(...)
boolean renameFile(Context context, String newName, String displayName) {
try {
Long id = getIdFromDisplayName(displayName);
ContentResolver contentResolver = context.getContentResolver();
Uri mUri = ContentUris.withAppendedId(extUri, id);
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 1);
contentResolver.update(mUri, contentValues, null, null);
contentValues.clear();
contentValues.put(MediaStore.Files.FileColumns.DISPLAY_NAME, newName);
// contentValues.put(MediaStore.Files.FileColumns.MIME_TYPE, "files/pdf");
// contentValues.put(MediaStore.Files.FileColumns.RELATIVE_PATH, relativeLocation);
// contentValues.put(MediaStore.Files.FileColumns.TITLE, "SomeName");
// contentValues.put(MediaStore.Files.FileColumns.DATE_ADDED, System.currentTimeMillis() / 1000);
// contentValues.put(MediaStore.Files.FileColumns.DATE_TAKEN, System.currentTimeMillis());
contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0);
contentResolver.update(mUri, contentValues, null, null);
return true;
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
function getIdFromDisplayName(...)
#RequiresApi(api = Build.VERSION_CODES.Q)
Long getIdFromDisplayName(String displayName) {
String[] projection;
projection = new String[]{MediaStore.Files.FileColumns._ID};
// TODO This will break if we have no matching item in the MediaStore.
Cursor cursor = getContentResolver().query(extUri, projection,
MediaStore.Files.FileColumns.DISPLAY_NAME + " LIKE ?", new String[]{displayName}, null);
assert cursor != null;
cursor.moveToFirst();
if (cursor.getCount() > 0) {
int columnIndex = cursor.getColumnIndex(projection[0]);
long fileId = cursor.getLong(columnIndex);
cursor.close();
return fileId;
}
return null;
}
java.lang.IllegalArgumentException: Movement of content://media/external/file/116 which isn't part of well-defined collection not allowed
So it is for Android Q not allowed if you use the collection;
Uri extUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
But is is allowed for a 'well-defined collection' like:
Uri extUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
// Use "Pictures/MyFolder" for RELATIVE_PATH
I leave it to you to find other well-defined collections.
Why this is only for Android Q i dont know.
You can see the message in the java file: https://android.googlesource.com/platform/packages/providers/MediaProvider/+/refs/heads/master/src/com/android/providers/media/MediaProvider.java
Quote:
// We only support movement under well-defined collections
switch (match) {
case AUDIO_MEDIA_ID:
case VIDEO_MEDIA_ID:
case IMAGES_MEDIA_ID:
case DOWNLOADS_ID:
break;
default:
throw new IllegalArgumentException("Movement of " + uri
+ " which isn't part of well-defined collection not allowed");
}
If the rename fails use SAF (as mentioned before). How to rename a file in Android knowing only its media content Uri
I had to face the rename problem myself (Android 29) and the solution above did not suffice.
This was because I had a physical SD card on which were located the
files I wanted to rename.
Then, instruction:
extUri = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
did not work; instead,I had to:
list the "external volumes"(according to Android terms)
Set<String> lVls = MediaStore.getExternalVolumeNames(this);
..which gave me 2 volumes:
"external_primary" (the built-in external storage)
"bc21-eafa" (the SD card external storage)
Initialize 'extUri' with that second value, like that:
extUri = MediaStore.Audio.Media.getContentUri("bc21-eafa");
Apply the rest of the procedure as described in this article.
Thanks to all !
Because of the Android Privacy Changes in Android Q (API29) it's not possible to add songs to a Playlist and it throws this error message when adding a track.
java.lang.SecurityException: com.mp3player.mp3player has no access to content://media/external_primary/audio/media/117
I know that we can this catch this as a RecoverableSecurityException and grant permission for each file individually.
But this is really a hassle and i'm wondering if there is another way.
I already found a post from User #Theo with the same exact problem but without any answers.
Code for adding songs to a playlist
public void addToPlayList(Context c, long songID, long playListID, String playlistName) {
Uri playListUri = MediaStore.Audio.Playlists.Members.getContentUri("external", playListID);
String[] columns = {
MediaStore.Audio.Playlists.Members.AUDIO_ID,
MediaStore.Audio.Playlists.Members.PLAY_ORDER,
};
ContentResolver resolver = c.getContentResolver();
Cursor cursor = resolver.query(playListUri, columns, null, null, null);
int playOrder = 0;
if (cursor != null) {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
playOrder = cursor.getInt(0) + 1;
}
cursor.close();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, songID);
contentValues.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, playOrder);
resolver.insert(playListUri, contentValues);
resolver.notifyChange(Uri.parse("content://media"), null);
}
EDIT
Looks like the thrown Exception is not an instance of RecoverableSecurityException so how do we get access to that content?
you can use playListUri.getpath() and solve it.
I'm trying to create an application to display the call logs based on the call type (incoming calls, outgoing calls, or missing calls). In addition I'm trying to add search and delete functionalities so the user can search for the call (by number) and delete the call. The layout of the app is shown here:
The search functionality works if I hit the 'All' button to display all calls and search by number there, but upon going to other sections to search for a number, such as received or missed, the app crashes.
So far I have managed to run the logcat on Android Studio, and found that the main issue is in my main activity file. I have attached the logcat image here:
There seems to be issues with these pieces of code: my getCalls Method, afterTextChanged Method, and my updateCursor Method.
private Cursor getCalls(int type, String searchString) {
Uri callUri = CallLog.Calls.CONTENT_URI;
ContentResolver contentResolver = getContentResolver();
String[] projection = new String[]{Calls._ID, Calls.NUMBER, Calls.DURATION, Calls.TYPE};
String selection=null;
String[] selectionArgs=null;
if(type != 0){
// filter type calls
selection = Calls.TYPE + "=?";
selectionArgs = new String[]{String.valueOf(type)};
}
if(!TextUtils.isEmpty(searchString)) {
// has some search string
if(TextUtils.isEmpty(selection)) {
// all call types
selection = Calls.NUMBER + " LIKE ?";
selectionArgs = new String[]{"%"+searchString+"%"};
} else {
// some type of call and add search String
selection = selection+" && " + Calls.NUMBER+" LIKE ?";
selectionArgs = new String[]{selectionArgs[0],"'%"+searchString+"%'"};
}
}
String order = Calls.DATE + " DESC ";
//verify permissions to access the user's call log
int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
cursor = contentResolver.query(callUri, // URI content provider
projection,
selection,
selectionArgs,
order);
}
return cursor;
}
#Override
public void afterTextChanged(Editable s) {
updateCursor();
}
//updates the search
void updateCursor() {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
cursor = null;
}
cursor = getCalls(currentCallType, searchET.getText().toString());
adapter.swapCursor(cursor);
}
Upon running the app, I expected to be able to go to different sections (for example, I go to the received call section) and search for a number, however upon going to the section and tapping on the search bar, the app crashes. I do not understand how there could be issues with these methods.
SQLException says the error is near the & symbol, so the error should be in this line:
selection = selection+" && " + Calls.NUMBER+" LIKE ?";
Let's replace it with this one, because 'AND' should be used in SQL instead of double &:
selection = selection+" AND " + Calls.NUMBER+" LIKE ?";
I am trying to access all of the WeChat contacts in my Android app and open Chat page with the contact on WeChat if the user taps on it. I read the official documentation from Here but it didn't help. I couldn't find any helpful answers anywhere else either. In my code, I am filtering contacts by MIME Type but I am getting an empty string every time. Please help me solve it...
//MIMETYPE of WeCha
String mimeString = "vnd.android.cursor.item/vnd.com.tencent.mm.chatting.voip.video";
String displayName = null;
String phone = null;
Long _id;
ContentResolver resolver = getApplicationContext().getContentResolver();
//Sorting contacts Alphabetically
Cursor cursor = resolver.query(ContactsContract.Data.CONTENT_URI, null, null, null, ContactsContract.Contacts.DISPLAY_NAME);
while (cursor.moveToNext()) {
_id = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data._ID));
phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
//Getting the MimeType of user
String mimeType = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE));
If(mimeType==mimeString)
{
//Logs for debugging
Log.d("Look here", _id.toString());
Log.d("Look here", displayName);
Log.d("Look here", mimeType);
}
}
cursor.close();