如何在Android App中获取并展示WhatsApp用户状态?实时获取可行吗?
Hey there! Let's walk through how to build an Android Activity that displays WhatsApp statuses, including real-time updates. First, some critical context you need to know:
WhatsApp doesn't offer an official public API to fetch user statuses directly. The only way to access these statuses is by reading the local storage directory where WhatsApp temporarily saves friends' status media (images/videos). Keep in mind:
- This method relies on WhatsApp's current storage structure — if they change it in an update, your implementation might break.
- Android 10+ Scoped Storage restrictions mean you can't directly access this folder without explicit user permission.
For Android 11 and above, you need to ask the user to manually grant access to WhatsApp's hidden status folder (Android/media/com.whatsapp/WhatsApp/Media/.Statuses). Here's how to trigger the directory picker:
private const val REQUEST_CODE_PICK_WHATSAPP_DIR = 101 fun launchWhatsAppDirPicker() { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) // Pre-select the WhatsApp status directory if possible val initialUri = Uri.parse("content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fmedia%2Fcom.whatsapp%2FWhatsApp%2FMedia%2F.Statuses") intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, initialUri) startActivityForResult(intent, REQUEST_CODE_PICK_WHATSAPP_DIR) } // Handle the result in onActivityResult (or registerForActivityResult for newer APIs) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == REQUEST_CODE_PICK_WHATSAPP_DIR && resultCode == RESULT_OK) { data?.data?.let { selectedDirUri -> // Save this URI for future access (use SharedPreferences) saveSelectedDirUri(selectedDirUri) // Load status files immediately loadStatusFiles(selectedDirUri) } } }
Once you have access to the directory, use ContentResolver to iterate through the media files. These files are the temporary statuses saved by WhatsApp:
// Data class to hold status file info data class StatusFile( val name: String, val mimeType: String, val lastModified: Long, val uri: Uri ) fun loadStatusFiles(dirUri: Uri) { val statusFiles = mutableListOf<StatusFile>() val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree( dirUri, DocumentsContract.getTreeDocumentId(dirUri) ) contentResolver.query( childrenUri, null, null, null, "${DocumentsContract.Document.COLUMN_LAST_MODIFIED} DESC" // Sort newest first )?.use { cursor -> val nameCol = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DISPLAY_NAME) val mimeTypeCol = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_MIME_TYPE) val lastModifiedCol = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_LAST_MODIFIED) val docIdCol = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DOCUMENT_ID) while (cursor.moveToNext()) { val fileUri = DocumentsContract.buildDocumentUriUsingTree(dirUri, cursor.getString(docIdCol)) statusFiles.add( StatusFile( cursor.getString(nameCol), cursor.getString(mimeTypeCol), cursor.getLong(lastModifiedCol), fileUri ) ) } } // Update your RecyclerView with the loaded files updateStatusRecyclerView(statusFiles) }
To detect when new statuses are added (or old ones are deleted by WhatsApp), use a ContentObserver to monitor changes in the directory:
private lateinit var statusObserver: ContentObserver override fun onStart() { super.onStart() val selectedDirUri = getSavedDirUri() // Retrieve from SharedPreferences selectedDirUri?.let { uri -> statusObserver = object : ContentObserver(Handler(Looper.getMainLooper())) { override fun onChange(selfChange: Boolean, changedUri: Uri?) { super.onChange(selfChange, changedUri) // Refresh status list when directory changes loadStatusFiles(uri) } } val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, DocumentsContract.getTreeDocumentId(uri)) contentResolver.registerContentObserver(childrenUri, true, statusObserver) } } override fun onStop() { super.onStop() contentResolver.unregisterContentObserver(statusObserver) }
Use a RecyclerView to display status thumbnails (matching the layout you referenced in your attachment):
- Item Layout: Create a layout for each status item with an ImageView for the thumbnail (add a play icon overlay for videos).
- RecyclerView Adapter:
class StatusAdapter( private val statusList: List<StatusFile>, private val onItemClick: (StatusFile) -> Unit ) : RecyclerView.Adapter<StatusAdapter.StatusViewHolder>() { inner class StatusViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val thumbnail: ImageView = itemView.findViewById(R.id.iv_status_thumbnail) val playIcon: ImageView = itemView.findViewById(R.id.iv_play_icon) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StatusViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_status, parent, false) return StatusViewHolder(view).apply { itemView.setOnClickListener { onItemClick(statusList[adapterPosition]) } } } override fun onBindViewHolder(holder: StatusViewHolder, position: Int) { val status = statusList[position] if (status.mimeType.startsWith("image/")) { holder.playIcon.visibility = View.GONE Glide.with(holder.thumbnail.context) .load(status.uri) .centerCrop() .into(holder.thumbnail) } else if (status.mimeType.startsWith("video/")) { holder.playIcon.visibility = View.VISIBLE // Load video thumbnail val thumbnail = ThumbnailUtils.createVideoThumbnail( status.uri.path, MediaStore.Video.Thumbnails.MINI_KIND ) holder.thumbnail.setImageBitmap(thumbnail) } } override fun getItemCount() = statusList.size }
- Setup RecyclerView in Activity:
fun updateStatusRecyclerView(statusList: List<StatusFile>) { val recyclerView = findViewById<RecyclerView>(R.id.rv_statuses) recyclerView.layoutManager = GridLayoutManager(this, 3) // Adjust grid columns as needed recyclerView.adapter = StatusAdapter(statusList) { status -> // Launch full-screen view activity on click val intent = Intent(this, StatusDetailActivity::class.java) intent.putExtra("STATUS_URI", status.uri) intent.putExtra("STATUS_MIME_TYPE", status.mimeType) startActivity(intent) } }
- WhatsApp Directory Changes: WhatsApp might alter its storage path in future updates — test your app regularly to ensure compatibility.
- Privacy Compliance: Your app must disclose in its privacy policy that it accesses WhatsApp's local status files, and you must not collect or share this data without user consent.
- File Lifespan: WhatsApp automatically deletes status files after 24 hours, so your app's displayed statuses will mirror this behavior.
内容的提问来源于stack exchange,提问作者Nauman Shafqat

