如何使用TYPE_INPUT_METHOD、TYPE_WALLPAPER创建View及解决Bad token Error
Hey there, let's break down how to properly use these two window types and fix that annoying Bad Token Error you're seeing. The key thing to understand here is that TYPE_INPUT_METHOD and TYPE_WALLPAPER aren't generic system overlay types like TYPE_SYSTEM_ALERT—they're tied to specific system services and have strict requirements for how they're created.
1. Using TYPE_INPUT_METHOD
This window type is exclusively designed for input method editors (IMEs)—think custom keyboards or input tools. You can't just create a random View and attach it to WindowManager with this type; it needs to be part of an InputMethodService, which handles token validation with WMS automatically.
Step-by-Step Implementation:
- Create an InputMethodService subclass: This is the core component that manages the input method View.
public class CustomInputMethod extends InputMethodService { @Override public View onCreateInputView() { // Inflate your custom input layout LayoutInflater inflater = getLayoutInflater(); View inputView = inflater.inflate(R.layout.custom_keyboard, null); // Add your input logic here (e.g., button click listeners for keys) return inputView; } } - Register the service in your Manifest: You need specific permissions and metadata to let the system recognize it as an IME.
<service android:name=".CustomInputMethod" android:permission="android.permission.BIND_INPUT_METHOD"> <meta-data android:name="android.view.im" android:resource="@xml/ime_config" /> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> </service> - Create the IME config XML: Define basic details like the input subtype and label.
<!-- res/xml/ime_config.xml --> <input-method xmlns:android="http://schemas.android.com/apk/res/android"> <subtype android:label="@string/custom_ime_label" android:imeSubtypeMode="keyboard" android:imeSubtypeLocale="en_US" /> </input-method> - Enable the IME: On your device, go to Settings > System > Languages & input > On-screen keyboard > Manage keyboards, then toggle on your custom IME.
2. Using TYPE_WALLPAPER
This type is for wallpaper-related Views, like dynamic wallpapers or wallpaper previews. Again, you can't attach a regular View with this type directly—you need to use WallpaperService, which handles WMS token checks.
Step-by-Step Implementation:
- Create a WallpaperService subclass: This manages the wallpaper's lifecycle and rendering.
public class CustomWallpaper extends WallpaperService { @Override public Engine onCreateEngine() { return new CustomWallpaperEngine(); } private class CustomWallpaperEngine extends Engine { private Paint textPaint; @Override public void onCreate(SurfaceHolder surfaceHolder) { super.onCreate(surfaceHolder); // Initialize drawing tools textPaint = new Paint(); textPaint.setColor(Color.WHITE); textPaint.setTextSize(60f); textPaint.setAntiAlias(true); } @Override public void onDraw(SurfaceHolder holder, Canvas canvas) { super.onDraw(holder, canvas); // Draw your custom wallpaper content canvas.drawColor(Color.DARK_GRAY); canvas.drawText("My Custom Wallpaper", 150f, 300f, textPaint); } } } - Register the service in your Manifest:
<service android:name=".CustomWallpaper" android:permission="android.permission.BIND_WALLPAPER"> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService" /> </intent-filter> <meta-data android:name="android.service.wallpaper" android:resource="@xml/wallpaper_config" /> </service> - Create the wallpaper config XML: Add a description and thumbnail for your wallpaper.
<!-- res/xml/wallpaper_config.xml --> <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/custom_wallpaper_desc" android:thumbnail="@drawable/wallpaper_thumb" /> - Set the wallpaper: On your device, go to Settings > Display > Wallpaper > Choose a new wallpaper, then select your custom wallpaper from the list.
Why You Were Getting the Bad Token Error
Unlike TYPE_SYSTEM_ALERT or TYPE_TOAST, which allow regular apps to add overlays (with the right permissions), TYPE_INPUT_METHOD and TYPE_WALLPAPER are restricted to their respective system services. When you try to add a View with these types directly via WindowManager, WMS rejects it because your app doesn't have the valid token that only the system-managed InputMethodService or WallpaperService can provide.
By using the dedicated service classes, you let the system handle token validation behind the scenes, eliminating the error.
内容的提问来源于stack exchange,提问作者hitwhyyx

