WhatsApp Status Save In Android 11 or above - java

Please guide me how to access whatsapp status folder in android 11?
I have seen status saver apps in play store that doesn't ask for any special permission but are still able to show statuses?
Tell me how can I access WhatsApp/Media/.Statuses folder in android 11?

You can solve it using the DocumentTreeIntent if you make it allow permission for the WhatsApp folder explicitly for android 11 here is how you can do that.
if (Constants.isPackageInstalled(getActivity(), "com.whatsapp")) {
Intent intent;
StorageManager sm = (StorageManager) getActivity().getSystemService(STORAGE_SERVICE);
String statusDir = getWhatsupFolder();
String str = "android.provider.extra.INITIAL_URI";
if (Build.VERSION.SDK_INT >= 29) {
intent = sm.getPrimaryStorageVolume().createOpenDocumentTreeIntent();
String scheme = ((Uri) intent.getParcelableExtra(str)).toString().replace("/root/", "/document/");
String stringBuilder = scheme +
"%3A" +
statusDir;
intent.putExtra(str, Uri.parse(stringBuilder));
} else {
intent = new Intent("android.intent.action.OPEN_DOCUMENT_TREE");
intent.putExtra(str, Uri.parse(statusDir));
}
intent.addFlags(2);
intent.addFlags(1);
intent.addFlags(128);
intent.addFlags(64);
startActivityForResult(intent, REQUEST_ACTION_OPEN_DOCUMENT_TREE);
return;
}
before using this code you must check if WhatsApp is installed or not so the first check is for that here is the code for that.
try {
context.getPackageManager().getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
after granting permission you must retrieve files via this code
private DocumentFile[] getFromSdcard() {
DocumentFile fromTreeUri = DocumentFile.fromTreeUri(requireContext().getApplicationContext(), Uri.parse(namedataprefs));
if (fromTreeUri != null && fromTreeUri.exists() && fromTreeUri.isDirectory() && fromTreeUri.canRead() && fromTreeUri.canWrite()) {
return fromTreeUri.listFiles();
}
return null;
}
DocumentFile[] allFiles = getFromSdcard();
//to get signal file path
String path = allFiles[0].getUri().toString();
you can get further details about document tree intent from the below code its just for understanding purposes
Ref : How to check which StorageVolume we have access to, and which we don't?
requestAccessButton.setOnClickListener {
storageVolumes = storageManager.storageVolumes
val primaryVolume = storageManager.primaryStorageVolume
val intent = primaryVolume.createOpenDocumentTreeIntent()
startActivityForResult(intent, 1)
}
}
private fun checkAccessToStorageVolumes() {
val storageVolumePathsWeHaveAccessTo = HashSet<String>()
val persistedUriPermissions = contentResolver.persistedUriPermissions
persistedUriPermissions.forEach {
storageVolumePathsWeHaveAccessTo.add(it.uri.toString())
}
val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolumes = storageManager.storageVolumes
for (storageVolume in storageVolumes) {
val uuid = if (storageVolume.isPrimary) {
// Primary storage doesn't get a UUID here.
"primary"
} else {
storageVolume.uuid
}
val volumeUri = uuid?.let { buildVolumeUriFromUuid(it) }
when {
uuid == null ->
Log.d("AppLog", "UUID is null for ${storageVolume.getDescription(this)}!")
storageVolumePathsWeHaveAccessTo.contains(volumeUri) ->
Log.d("AppLog", "Have access to $uuid")
else -> Log.d("AppLog", "Don't have access to $uuid")
}
}
}
private fun buildVolumeUriFromUuid(uuid: String): String {
return DocumentsContract.buildTreeDocumentUri(
"com.android.externalstorage.documents",
"$uuid:"
).toString()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.d("AppLog", "resultCode:$resultCode")
val uri = data?.data ?: return
val takeFlags =
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
contentResolver.takePersistableUriPermission(uri, takeFlags)
Log.d("AppLog", "granted uri: ${uri.path}")
}

For Fetch Whatsapp Status in Android 11 You have to Fetch this status from this path.
which is written below:-
Android->media->com.whatsapp->WhatsApp->Media->.Statues->"You can see all statues which was show by user"

You can try this Path. it may be helpful for you.
For Android-10 and above
File(Environment.getExternalStorageDirectory() + File.separator + "Android/media/com.whatsapp/WhatsApp/Media/.Statuses")
Below Android-10 Version
File(Environment.getExternalStorageDirectory() + File.separator + "WhatsApp/Media/.Statuses")

Related

automatic update android app apk without playstore

I'm building an app (android studio - java) for my several devices, the app won't be on app store.
I want to be able to update the app remotely automatically.
I figured out how to check the version against a server, however I still don't know how to automatically update the app whenever the is a new version.
Thanks a head!
Firstly, as you said, you need to check the latest version, online and locally.
Then you need to put the apk newest apk online
Finally, if the online version is ahead the local, you need to download the file and update the app.
The easiest way to do it is to use the ota_update package to download and update the app
I hope this solution is useful for you
First you have to store the latest version on the server side using API.
After that you have to compare the installed current app version to the server-side stored version if both are different and the current version lower than the server-side version at that time you have to perform the below code.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!getPackageManager().canRequestPackageInstalls()) {
startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).setData(Uri.parse(String.format("package:%s", getPackageName()))), 1234);
} else {
downloadController = new DownloadController(DashboardNewActivity.this, url);
downloadController.enqueueDownload();
}
}
Use this DownloadController.kt class
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.util.Log
import android.widget.Toast
import androidx.core.content.FileProvider
import com.app.golden.BuildConfig
import com.app.golden.R
import java.io.File
class DownloadController(private val context: Context, private val url: String) {
companion object {
private const val FILE_NAME = "company.apk"
private const val FILE_BASE_PATH = "file://"
private const val MIME_TYPE = "application/vnd.android.package-archive"
private const val PROVIDER_PATH = ".provider"
private const val APP_INSTALL_PATH = "\"application/vnd.android.package-archive\""
}
fun enqueueDownload() {
var destination = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + "/"
destination += FILE_NAME
val uri = Uri.parse("$FILE_BASE_PATH$destination")
val file = File(destination)
if (file.exists()) file.delete()
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadUri = Uri.parse(url)
val request = DownloadManager.Request(downloadUri)
request.setMimeType(MIME_TYPE)
request.setTitle(context.getString(R.string.app_name))
request.setDescription(context.getString(R.string.downloading))
// set destination
request.setDestinationUri(uri)
showInstallOption(destination, URI)
// Enqueue a new download and same the referenced
downloadManager.enqueue(request)
Toast.makeText(context, context.getString(R.string.downloading), Toast.LENGTH_LONG)
.show()
}
private fun showInstallOption(
destination: String,
uri: Uri
) {
// set BroadcastReceiver to install app when .apk is downloaded
val onComplete = object : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent
) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val contentUri = FileProvider.getUriForFile(
context,
BuildConfig.APPLICATION_ID + PROVIDER_PATH,
File(destination)
)
val install = Intent(Intent.ACTION_VIEW)
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
install.data = contentUri
context.startActivity(install)
context.unregisterReceiver(this)
} else {
val install = Intent(Intent.ACTION_VIEW)
install.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
install.setDataAndType(
uri,
APP_INSTALL_PATH
)
context.startActivity(install)
context.unregisterReceiver(this)
}
} catch (e: Exception) {
val data = e.message.toString()
Log.e("Exception: ", data)
}
}
}
context.registerReceiver(onComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
}
}

Extract QueryParameters from deeplink Url in Kotlin

Please help guys, Im using firebase dynamic links, i want to know how we can extract our pass string queryparameters in kotlin. this is the generated deeplink:
deeplink = https://demo.com/?roomCode=myroomtest%3FroomToken%3DOiJIUzI1NiJ
how to extract roomCode=myroomtest, roomToken=OiJIUzI1NiJ this string values from deeplink url.
private fun handleDynamicLink() {
Firebase.dynamicLinks
.getDynamicLink(intent)
.addOnSuccessListener { pendingDynamicLinkData ->
val deepLink: Uri?
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.link
what queryparameter should i use here to extract the strings from deeplink?
}
}
.addOnFailureListener { _ ->
toast(getString(R.string.main_error_fetch_dynamic_link))
}
}
I need the strings so that i can start meeting using the following code:
private fun joinMeeting (roomCode:String, roomToken:String) {
MeetingUtils.startMeeting(
this,
roomCode,
roomToken)
}
Finally it is resolved:
private fun handleDynamicLink() {
Firebase.dynamicLinks
.getDynamicLink(intent)
.addOnSuccessListener { pendingDynamicLinkData ->
val deepLink: Uri?
if (pendingDynamicLinkData != null) {
deepLink = pendingDynamicLinkData.link
val roomCode = deepLink?.getQueryParameter("roomCode")?.substringBefore("?roomToken=","")
val roomToken = deepLink?.getQueryParameter("roomCode")?.replace("roomToken","roomToken")?.substringAfter("?roomToken=","")
if(roomCode !=null && roomToken != null) {
joinMeeting(roomCode, roomToken)
}
}
}
.addOnFailureListener { _ ->
toast(getString(R.string.main_error_fetch_dynamic_link))
}
}

How to read incoming MMS and SMS messages on Android

I know this is a big topic, as seen here and here, so I just wanted to post how I solved both the issue of receiving incoming MMS and SMS messages and the issue of grabbing data from those MMS and SMS messages on Android 9.0 version 28+ using Xamarin.Forms. This code can easily be translated to Java. Here is the completed Android app so you can try it yourself. It also shows how to do some Azure machine learning if you're interested in that.
For Broadcast Receivers:
Classes, registering class instances , permissions needed.
Note that the broadcast receivers were added dynamically, they can be added statically using Xamarin's intent-filter decorator , or (if you're not using Xamarin) the AndroidManifest.xml file.
Here is a code snippet to show how to parse incoming SMS data with a Broadcast Receiver:
public override void OnReceive(Context context, Intent intent)
{
Log.Info(TAG, "Intent action received: " + intent.Action);
// Retrieve message from the intent and analyze it.
SmsMessage msg = Android.Provider.Telephony.Sms.Intents.GetMessagesFromIntent(intent)[0];
string message = msg.DisplayMessageBody;
(string, bool) result = MMSReceiver.CleanUpMessage(message);
// If there were one or more rooster words.
if (result.Item2)
{
string title = "Rooster Text Received From: " + msg.DisplayOriginatingAddress;
DependencyService.Get<INotificationManager>().ScheduleNotification(title, result.Item1);
}
}
And here is a code snippet to show how to parse incoming MMS data with a Broadcast Receiver:
public override void OnReceive(Context context, Intent intent)
{
Log.Info(TAG, "Intent action received: " + intent.Action);
// Get the MMS ID. Adapted from: https://stackoverflow.com/questions/10065249/how-to-get-mms-id-android-application
ContentResolver contentResolver = AndroidApp.Context.ContentResolver;
Android.Net.Uri mmsInboxUri = Android.Net.Uri.Parse("content://mms");
Android.Database.ICursor mmsInboxCursor = contentResolver.Query(mmsInboxUri, new string[]
{"_id","msg_box","ct_t","date"}, "msg_box=1 or msg_box=2", null, null);
int id = -1;
if (mmsInboxCursor != null)
{
try
{
if (mmsInboxCursor.MoveToFirst())
{
id = Int32.Parse(mmsInboxCursor.GetString(0));
Log.Info(TAG, "Id is this: " + mmsInboxCursor.GetString(0));
}
}
catch (System.Exception error)
{
Log.Error(TAG, "Error requesting the MMS ID: " + error.Message);
}
}// if (mmsInboxCursor != null)
// Get text and picture from MMS message. Adapted from: https://stackoverflow.com/questions/3012287/how-to-read-mms-data-in-android
string message = ""; // text
Android.Graphics.Bitmap bitmap = null; // picture
string selectionPart = "mid=" + id;
Android.Net.Uri mmsTextUri = Android.Net.Uri.Parse("content://mms/part");
Android.Database.ICursor cursor = contentResolver.Query(mmsTextUri, null,
selectionPart, null, null);
if (cursor.MoveToFirst())
{
do
{
string partId = cursor.GetString(cursor.GetColumnIndex("_id"));
string type = cursor.GetString(cursor.GetColumnIndex("ct"));
// Get text.
if ("text/plain".Equals(type))
{
string data = cursor.GetString(cursor.GetColumnIndex("_data"));
if (data != null)
{
message = GetMmsText(partId);
Log.Info(TAG, "Body is this: " + message);
}
else
{
message = cursor.GetString(cursor.GetColumnIndex("text"));
Log.Info(TAG, "Body is this: " + message);
}
}
//Get picture.
if ("image/jpeg".Equals(type) || "image/bmp".Equals(type) ||
"image/gif".Equals(type) || "image/jpg".Equals(type) ||
"image/png".Equals(type))
{
bitmap = GetMmsImage(partId);
}
} while (cursor.MoveToNext());
}// if (cursor.MoveToFirst())
}

I am facing issues with creating, deleting, moving, coping files using Intent.ACTION_OPEN_DOCUMENT

When I select file to manipulate from internal storage using Intent.ACTION_DOCUMENT_OPEN, logcat logs an error described below.
java.lang.SecurityException: Permission Denial: reading com.android.providers.downloads.DownloadStorageProvider uri content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2FrenamedName%20(1).db from pid=5361, uid=10398 requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
intentToGetContentcode -> {
if (resultCode == Activity.RESULT_OK) {
val uri = data!!.data!!
// ...permissions grantUriPermissions
grantUriPermission(
"com.velabs.rerinavi2",
uri,
Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
)
grantUriPermission(
"com.velabs.rerinavi2",
uri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
grantUriPermission(
"com.velabs.rerinavi2",
uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
val resolver = applicationContext.contentResolver
val cursor =
this.contentResolver.query(uri, null, null, null, null)
resolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION and Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
// val path: Uri = FileProvider.getUriForFile(
// context,
// "com.velabs.rerinavi.fileprovider",
// filelocation
// )
val type = resolver.getType(uri)
l("MIME type of .db",type!!)
try {
val path = getDatabasePath("renamedName(1).db").absolutePath
l("renamedName(1) path",path)
}catch (e:Exception){
l("documentFile","error $e,,,,"+DocumentFile.fromSingleUri(this,uri)!!.isFile.toString())
}
try {
val doc = DocumentsContract.renameDocument(resolver, uri, "renamedName.db")
}catch (e:Exception) {
l("rename",e.toString())
}
try {
val file = resolver.openInputStream(uri)
// val homeFile = getDatabasePath("export.db").outputStream()
// file!!.copyTo(homeFile)
}catch (e:Exception) {
l("copyTo",e.toString())
}
}
}
super.onActivityResult(requestCode, resultCode, data)
}
(Apologies for the messy code, I am still learning)
An illustration of how to copy a file from internal storage to one's app's database directory would be extremely helpful.
Here's the intent I am using:
private fun exportToLocation() {
if(checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED &&
checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
requestPermissions(arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE,android.Manifest.permission.WRITE_EXTERNAL_STORAGE),requestPermissionCode)
}else {
val intentToGetContent =
Intent(Intent.ACTION_OPEN_DOCUMENT) //ACTION_GET_CONTENT replaced by opendocuments //action_open_doc works
intentToGetContent.addCategory(Intent.CATEGORY_OPENABLE)
intentToGetContent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
intentToGetContent.type =
"application/octet-stream" //application/db doesn't work //application/octect-stream works
// inference for above application is correct /(this part needs to be corrected)
startActivityForResult(
Intent.createChooser(intentToGetContent, "Import file"),
intentToGetContentcode
)
}

Convert mime types in fileChooserParams to the right format for Intent.setType

I am trying to upload a file using a WebView in Android.
This is the code in use:
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
Intent intent = fileChooserParams.createIntent();
LOG.d(LOG_TAG, "mime types: " + Arrays.toString(fileChooserParams.getAcceptTypes()));
// PRINTS [.jpg,.png,.tiff,.jpeg,.tif,.pdf] !!
try {
parentEngine.cordova.startActivityForResult(new CordovaPlugin() {
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// ...
}
}, intent, FILECHOOSER_RESULTCODE);
} catch (ActivityNotFoundException e) {
// ...
}
return true;
}
The problem is that when the external library that I must use (ng-file-upload) triggers the execution of this method, the mime types passed as argument in fileChooserParams are: [.jpg,.png,.tiff,.jpeg,.tif,.pdf]. I don't see most of these in the list of allowed mime types.
As a consequence I find this error in LogCat:
No activity found to handle file chooser intent.: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT cat=[android.intent.category.OPENABLE] typ=.jpg,.png,.tiff,.jpeg,.tif,.pdf }
If I simply add intent.setType("image/* application/pdf"); everything works as expected!
Now the question is: in the Merge Request that I want to submit to cordova-android's contributors how do I safely transform the fileChooserParams to the correct format?
I improved the solution using this code:
// Validation utility for mime types
private List<String> extractValidMimeTypes(String[] mimeTypes) {
List<String> results = new ArrayList<String>();
List<String> mimes;
if (mimeTypes.length() == 1 && mimeTypes[0].contains(",")) {
mimes = Arrays.asList(mimeTypes[0].split(","));
} else {
mimes = Arrays.asList(mimeTypes);
}
MimeTypeMap mtm = MimeTypeMap.getSingleton();
for (String mime : mimes) {
if (mime != null && mime.trim().startsWith(".")) {
String extensionWithoutDot = mime.trim().substring(1, mime.trim().length());
String derivedMime = mtm.getMimeTypeFromExtension(extensionWithoutDot);
if (derivedMime != null && !results.contains(derivedMime)) {
// adds valid mime type derived from the file extension
results.add(derivedMime);
}
} else if (mtm.getExtensionFromMimeType(mime) != null && !results.contains(mime)) {
// adds valid mime type checked agains file extensions mappings
results.add(mime);
}
}
return results;
}
public boolean onShowFileChooser(WebView webView, final ValueCallback<Uri[]> filePathsCallback, final WebChromeClient.FileChooserParams fileChooserParams) {
Intent intent = fileChooserParams.createIntent();
List<String> validMimeTypes = extractValidMimeTypes(fileChooserParams.getAcceptTypes());
if (validMimeTypes.isEmpty()) {
intent.setType(DEFAULT_MIME_TYPE);
} else {
intent.setType(String.join(" ", validMimeTypes));
}
...
See my Pull Request for more details.
I resolved simply adding the following 2 lines in my PR:
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, fileChooserParams.getAcceptTypes());
Outcome:
2019-04-01 00:18:00.501 32500-32500/my.app.bundle.id D/SystemWebChromeClient: : fileChooserParams.getAcceptTypes(): [.jpg,.png,.tiff,.jpeg,.tif,.pdf]
2019-04-01 00:18:00.503 2225-2921/system_process I/ActivityManager: START u0 {act=android.intent.action.GET_CONTENT cat=[android.intent.category.OPENABLE] typ=image/* cmp=com.android.documentsui/.picker.PickActivity (has extras)} from uid 10105
I hope it will get accepted.

Categories