367 lines
10 KiB
Bash
Executable File
367 lines
10 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ============================================================
|
|
# Messages Mod+ Standalone Script
|
|
# Fix RCS on rooted Android devices by reinstalling
|
|
# Google Messages as a user-space app
|
|
#
|
|
# Run from a computer with ADB connected to a rooted device
|
|
# ============================================================
|
|
|
|
set -euo pipefail
|
|
|
|
# ---- USER CONFIGURABLE VARIABLES ----
|
|
# Set these manually, or leave empty for auto-detection
|
|
MSG_PKG="" # e.g. "com.google.android.apps.messaging"
|
|
BACKUP_DIR="" # e.g. "./messages_backup"
|
|
# ---- END USER CONFIG ----
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
|
|
log() { echo -e "${BLUE}[*]${NC} $1"; }
|
|
ok() { echo -e "${GREEN}[+]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
|
err() { echo -e "${RED}[-]${NC} $1"; }
|
|
hdr() { echo -e "\n${BOLD}${CYAN}=== $1 ===${NC}\n"; }
|
|
|
|
su_cmd() {
|
|
adb shell su -c "$1" 2>&1
|
|
}
|
|
|
|
check_adb() {
|
|
if ! command -v adb &>/dev/null; then
|
|
err "ADB not found in PATH"
|
|
exit 1
|
|
fi
|
|
|
|
local devices
|
|
devices=$(adb devices | grep -w "device" | grep -v "List")
|
|
if [ -z "$devices" ]; then
|
|
err "No ADB device connected"
|
|
exit 1
|
|
fi
|
|
|
|
local serial
|
|
serial=$(echo "$devices" | head -1 | awk '{print $1}')
|
|
ok "Device connected: ${serial}"
|
|
}
|
|
|
|
check_root() {
|
|
local whoami
|
|
whoami=$(su_cmd 'id -u' | tr -d '[:space:]')
|
|
if [ "$whoami" != "0" ]; then
|
|
err "Root shell not available (su failed)"
|
|
err "Make sure KernelSU, Magisk, or another root solution is active"
|
|
exit 1
|
|
fi
|
|
ok "Root shell verified"
|
|
}
|
|
|
|
auto_detect() {
|
|
log "Auto-detecting Google Messages package..."
|
|
|
|
# Try the standard package name
|
|
local found
|
|
found=$(adb shell pm list packages 2>/dev/null | grep "com.google.android.apps.messaging" || true)
|
|
|
|
if [ -n "$found" ]; then
|
|
MSG_PKG="com.google.android.apps.messaging"
|
|
ok "Found: ${MSG_PKG}"
|
|
else
|
|
# Broader search
|
|
warn "Standard package not found, searching..."
|
|
found=$(adb shell pm list packages 2>/dev/null | grep -i "messaging\|messages" || true)
|
|
if [ -n "$found" ]; then
|
|
echo ""
|
|
echo "Found messaging packages:"
|
|
echo "$found" | sed 's/package:/ /' | nl
|
|
echo ""
|
|
read -rp "Enter the number of the correct package (or type it manually): " choice
|
|
if [[ "$choice" =~ ^[0-9]+$ ]]; then
|
|
MSG_PKG=$(echo "$found" | sed 's/package://' | sed -n "${choice}p" | tr -d '[:space:]')
|
|
else
|
|
MSG_PKG="$choice"
|
|
fi
|
|
else
|
|
err "No messaging packages found on device"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
BACKUP_DIR="${BACKUP_DIR:-./messages_backup_$(date +%Y%m%d)}"
|
|
}
|
|
|
|
manual_config() {
|
|
echo ""
|
|
read -rp "Enter Messages package name [com.google.android.apps.messaging]: " input_pkg
|
|
MSG_PKG="${input_pkg:-com.google.android.apps.messaging}"
|
|
|
|
read -rp "Enter local backup directory [./messages_backup]: " input_dir
|
|
BACKUP_DIR="${input_dir:-./messages_backup}"
|
|
|
|
# Verify package exists
|
|
if ! adb shell pm list packages | grep -q "$MSG_PKG"; then
|
|
err "Package '${MSG_PKG}' not found on device"
|
|
exit 1
|
|
fi
|
|
ok "Package verified: ${MSG_PKG}"
|
|
}
|
|
|
|
backup_databases() {
|
|
hdr "Backing Up Databases"
|
|
mkdir -p "${BACKUP_DIR}/databases"
|
|
|
|
# SMS/MMS
|
|
local sms_db="/data/data/com.android.providers.telephony/databases/mmssms.db"
|
|
log "Backing up SMS/MMS database..."
|
|
adb shell su -c "cat '${sms_db}'" > "${BACKUP_DIR}/databases/mmssms.db" 2>/dev/null && \
|
|
ok "SMS/MMS: $(du -h "${BACKUP_DIR}/databases/mmssms.db" | cut -f1)" || \
|
|
warn "SMS/MMS database not found or empty"
|
|
|
|
# RCS / Bugle
|
|
local rcs_db="/data/data/${MSG_PKG}/databases/bugle_db"
|
|
log "Backing up RCS database..."
|
|
adb shell su -c "cat '${rcs_db}'" > "${BACKUP_DIR}/databases/bugle_db.db" 2>/dev/null && \
|
|
ok "RCS: $(du -h "${BACKUP_DIR}/databases/bugle_db.db" | cut -f1)" || \
|
|
warn "RCS database not found or empty"
|
|
|
|
# Remove zero-byte files from failed backups
|
|
find "${BACKUP_DIR}/databases" -size 0 -delete 2>/dev/null || true
|
|
}
|
|
|
|
pull_apks() {
|
|
hdr "Pulling APK Splits"
|
|
mkdir -p "${BACKUP_DIR}/apks"
|
|
|
|
local apk_paths
|
|
apk_paths=$(adb shell su -c "pm path '${MSG_PKG}'" | sed 's/package://' | tr -d '\r')
|
|
|
|
if [ -z "$apk_paths" ]; then
|
|
err "Could not find APK paths for ${MSG_PKG}"
|
|
exit 1
|
|
fi
|
|
|
|
local count=0
|
|
while IFS= read -r apk_path; do
|
|
apk_path=$(echo "$apk_path" | tr -d '[:space:]')
|
|
[ -z "$apk_path" ] && continue
|
|
local apk_name
|
|
apk_name=$(basename "$apk_path")
|
|
log "Pulling ${apk_name}..."
|
|
adb shell su -c "cat '${apk_path}'" > "${BACKUP_DIR}/apks/${apk_name}"
|
|
local size
|
|
size=$(du -h "${BACKUP_DIR}/apks/${apk_name}" | cut -f1)
|
|
ok " ${apk_name} (${size})"
|
|
count=$((count + 1))
|
|
done <<< "$apk_paths"
|
|
|
|
ok "Pulled ${count} APK split(s)"
|
|
}
|
|
|
|
disable_system() {
|
|
hdr "Disabling System Messages"
|
|
log "Disabling ${MSG_PKG}..."
|
|
local result
|
|
result=$(adb shell su -c "pm disable-user --user 0 '${MSG_PKG}'" 2>&1)
|
|
echo " ${result}"
|
|
|
|
if echo "$result" | grep -q "disabled"; then
|
|
ok "System app disabled"
|
|
else
|
|
warn "Disable command returned unexpected output"
|
|
fi
|
|
}
|
|
|
|
reinstall_userspace() {
|
|
hdr "Reinstalling as User-Space App"
|
|
|
|
local apk_files
|
|
apk_files=$(ls -1 "${BACKUP_DIR}/apks/"*.apk 2>/dev/null)
|
|
local apk_count
|
|
apk_count=$(echo "$apk_files" | wc -l)
|
|
|
|
if [ -z "$apk_files" ] || [ "$apk_count" -eq 0 ]; then
|
|
err "No APK files found in ${BACKUP_DIR}/apks/"
|
|
exit 1
|
|
fi
|
|
|
|
log "Installing ${apk_count} APK split(s)..."
|
|
local install_args=""
|
|
while IFS= read -r apk; do
|
|
install_args="${install_args} ${apk}"
|
|
done <<< "$apk_files"
|
|
|
|
local result
|
|
if [ "$apk_count" -gt 1 ]; then
|
|
result=$(adb install-multiple $install_args 2>&1)
|
|
else
|
|
result=$(adb install $install_args 2>&1)
|
|
fi
|
|
|
|
echo " ${result}"
|
|
|
|
if echo "$result" | grep -qi "success"; then
|
|
ok "Installation successful"
|
|
else
|
|
err "Installation failed"
|
|
warn "Attempting to re-enable system app..."
|
|
adb shell pm enable "$MSG_PKG" 2>/dev/null
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
reenable_package() {
|
|
hdr "Re-enabling Package"
|
|
local result
|
|
result=$(adb shell pm enable "$MSG_PKG" 2>&1)
|
|
echo " ${result}"
|
|
ok "Package enabled"
|
|
}
|
|
|
|
verify() {
|
|
hdr "Verification"
|
|
local flags
|
|
flags=$(adb shell su -c "dumpsys package '${MSG_PKG}'" | grep "pkgFlags" | head -1)
|
|
|
|
if echo "$flags" | grep -q "UPDATED_SYSTEM_APP"; then
|
|
ok "Messages is running as UPDATED_SYSTEM_APP (user-space)"
|
|
echo ""
|
|
echo -e "${GREEN}${BOLD} Messages Mod+ applied successfully!${NC}"
|
|
echo ""
|
|
echo " Next steps on your device:"
|
|
echo " 1. Open Google Messages"
|
|
echo " 2. Set as default SMS app if prompted"
|
|
echo " 3. Grant permissions"
|
|
echo " 4. RCS should provision normally"
|
|
echo ""
|
|
else
|
|
warn "Package flags: ${flags}"
|
|
warn "State may not be as expected - verify on device"
|
|
fi
|
|
}
|
|
|
|
revert_to_stock() {
|
|
hdr "Reverting to Stock"
|
|
log "Removing user-space updates..."
|
|
adb shell pm uninstall-updates "$MSG_PKG" 2>&1 || true
|
|
adb shell pm enable "$MSG_PKG" 2>/dev/null
|
|
|
|
local flags
|
|
flags=$(adb shell su -c "dumpsys package '${MSG_PKG}'" | grep "pkgFlags" | head -1)
|
|
if echo "$flags" | grep -q "UPDATED_SYSTEM_APP"; then
|
|
warn "Revert may not have completed fully"
|
|
else
|
|
ok "Messages reverted to stock system app"
|
|
fi
|
|
}
|
|
|
|
show_menu() {
|
|
echo ""
|
|
echo -e "${BOLD}${CYAN}Messages Mod+${NC}"
|
|
echo -e "Fix RCS on rooted Android devices"
|
|
echo ""
|
|
echo " 1) Apply mod (full process)"
|
|
echo " 2) Backup databases only"
|
|
echo " 3) Revert to stock"
|
|
echo " 4) Check status"
|
|
echo " 5) Exit"
|
|
echo ""
|
|
read -rp "Select option [1-5]: " choice
|
|
echo ""
|
|
return "$choice"
|
|
}
|
|
|
|
show_status() {
|
|
hdr "Current Status"
|
|
local flags
|
|
flags=$(adb shell su -c "dumpsys package '${MSG_PKG}'" 2>/dev/null | grep "pkgFlags" | head -1 || echo "not found")
|
|
local code_path
|
|
code_path=$(adb shell su -c "dumpsys package '${MSG_PKG}'" 2>/dev/null | grep "codePath=" | head -1 | sed 's/.*codePath=//' || echo "unknown")
|
|
local enabled
|
|
enabled=$(adb shell pm list packages -e 2>/dev/null | grep -q "$MSG_PKG" && echo "Yes" || echo "No")
|
|
|
|
echo " Package: ${MSG_PKG}"
|
|
echo " Path: ${code_path}"
|
|
echo " Enabled: ${enabled}"
|
|
echo " Flags: ${flags}"
|
|
|
|
if echo "$flags" | grep -q "UPDATED_SYSTEM_APP"; then
|
|
ok "State: MODDED (user-space)"
|
|
elif echo "$flags" | grep -q "SYSTEM"; then
|
|
warn "State: SYSTEM (stock)"
|
|
else
|
|
log "State: Unknown"
|
|
fi
|
|
}
|
|
|
|
# ============================================================
|
|
# Main
|
|
# ============================================================
|
|
|
|
echo ""
|
|
echo -e "${BOLD}${CYAN}╔══════════════════════════════════╗${NC}"
|
|
echo -e "${BOLD}${CYAN}║ Messages Mod+ v1.0.0 ║${NC}"
|
|
echo -e "${BOLD}${CYAN}║ Fix RCS on Rooted Devices ║${NC}"
|
|
echo -e "${BOLD}${CYAN}╚══════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
# Preflight
|
|
check_adb
|
|
check_root
|
|
|
|
# Detection mode
|
|
echo ""
|
|
echo "Configuration mode:"
|
|
echo " 1) Auto-detect (recommended)"
|
|
echo " 2) Manual"
|
|
echo ""
|
|
read -rp "Select [1/2]: " mode
|
|
|
|
case "$mode" in
|
|
2) manual_config ;;
|
|
*) auto_detect ;;
|
|
esac
|
|
|
|
BACKUP_DIR="${BACKUP_DIR:-./messages_backup_$(date +%Y%m%d)}"
|
|
mkdir -p "$BACKUP_DIR"
|
|
log "Backup directory: ${BACKUP_DIR}"
|
|
|
|
# Main menu loop
|
|
while true; do
|
|
show_menu
|
|
opt=$?
|
|
|
|
case "$opt" in
|
|
1)
|
|
backup_databases
|
|
pull_apks
|
|
disable_system
|
|
reinstall_userspace
|
|
reenable_package
|
|
verify
|
|
;;
|
|
2)
|
|
backup_databases
|
|
;;
|
|
3)
|
|
revert_to_stock
|
|
;;
|
|
4)
|
|
show_status
|
|
;;
|
|
5)
|
|
echo "Bye!"
|
|
exit 0
|
|
;;
|
|
*)
|
|
warn "Invalid option"
|
|
;;
|
|
esac
|
|
done
|