You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android多进程场景下:如何检测库实例是否已在其他进程运行?

Android多进程下检测库实例是否已运行的解决方案

核心思路

Android多进程对应独立的虚拟机实例,跨进程状态共享需依赖系统级跨进程通信机制。以下是几种可靠的实现方案:

1. 文件锁(最可靠的排他性检测)

利用系统文件排他锁特性,确保同一时间仅一个进程能持有锁,以此判断库实例是否已运行:

private FileLock lock;
private FileChannel channel;

// 检测是否已有库实例运行
public boolean isLibraryAlreadyRunning(Context context) {
    File lockFile = new File(context.getFilesDir(), "library_instance_lock.lock");
    try {
        channel = new RandomAccessFile(lockFile, "rw").getChannel();
        // 尝试获取排他锁,获取失败说明已有进程持有
        lock = channel.tryLock();
        return lock == null;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

// 库销毁时主动释放锁(进程异常退出时系统也会自动释放)
public void releaseLibraryLock() {
    try {
        if (lock != null) lock.release();
        if (channel != null) channel.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

2. SharedPreferences标记位(需处理异常场景)

通过私有SharedPreferences存储运行标记,结合同步锁避免多进程竞争:

private static final String SP_NAME = "library_process_sync";
private static final String KEY_IS_RUNNING = "library_running_flag";

public boolean isLibraryAlreadyRunning(Context context) {
    SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
    boolean isRunning = sp.getBoolean(KEY_IS_RUNNING, false);
    
    if (!isRunning) {
        synchronized (YourLibraryClass.class) {
            // 二次检查避免多进程竞争
            isRunning = sp.getBoolean(KEY_IS_RUNNING, false);
            if (!isRunning) {
                sp.edit().putBoolean(KEY_IS_RUNNING, true).apply();
            }
        }
        return false;
    }
    return true;
}

// 库正常销毁时清除标记
public void markLibraryStopped(Context context) {
    SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
    sp.edit().putBoolean(KEY_IS_RUNNING, false).apply();
}

注意:进程异常退出时标记不会自动清除,需额外添加进程存活校验逻辑修正标记。

3. ContentProvider作为同步节点

利用ContentProvider跨进程访问且单实例运行的特性,将其作为库初始化的唯一入口:

public class LibrarySyncProvider extends ContentProvider {
    private static boolean isLibraryInitialized = false;

    @Override
    public boolean onCreate() {
        // 在此处执行库核心初始化逻辑
        isLibraryInitialized = true;
        return true;
    }

    // 对外暴露检测方法
    public static boolean isLibraryRunning(Context context) {
        // 触发Provider初始化
        context.getContentResolver().query(
                Uri.parse("content://com.your.library.sync/check"),
                null, null, null, null);
        return isLibraryInitialized;
    }

    // 以下方法实现空逻辑即可
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
}

在AndroidManifest.xml中注册Provider:

<provider
    android:name=".LibrarySyncProvider"
    android:authorities="com.your.library.sync"
    android:process=":library_process" /> <!-- 指定独立进程确保全局单实例 -->

优点:系统自动管理生命周期,异常退出时进程清理后会重新初始化,无需手动处理状态释放。

4. 进程存活检测(辅助方案)

通过ActivityManager遍历运行进程,结合进程名或类加载情况判断:

public boolean isLibraryProcessRunning(Context context) {
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();
    if (processes == null) return false;

    String targetProcessName = context.getPackageName() + ":library_process";
    for (ActivityManager.RunningAppProcessInfo process : processes) {
        if (process.processName.equals(targetProcessName)) {
            return true;
        }
        // 可选:通过反射检查进程是否加载库核心类(兼容性较差)
        try {
            Class.forName("com.your.library.core.LibraryCore", false, process.getClassLoader());
            return true;
        } catch (ClassNotFoundException ignored) {}
    }
    return false;
}

选型建议

  • 优先选择文件锁或ContentProvider方案,可靠性更高;
  • 若库仅允许在特定进程运行,可在初始化前先检查当前进程名,直接拒绝非目标进程的初始化请求;
  • 所有方案需考虑进程异常退出的场景,确保状态可以自动或手动修复。

内容的提问来源于stack exchange,提问作者user924941

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:20:24