国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android 如何優(yōu)雅地監(jiān)聽SystemProperties屬性值變化

這篇具有很好參考價(jià)值的文章主要介紹了Android 如何優(yōu)雅地監(jiān)聽SystemProperties屬性值變化。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

引言

我司項(xiàng)目中會(huì)頻繁用到persist.sys.xxx的屬性值,系統(tǒng)中預(yù)埋接口,通過屬性值控制,以應(yīng)對(duì)客戶多樣化的需求定制。
以往都是先設(shè)置屬性值,再重啟設(shè)備使能生效,抽空研究一下實(shí)時(shí)監(jiān)聽屬性值變化,最后在csdn上查到監(jiān)聽SystemProperties變化 這篇文章。
博主的實(shí)現(xiàn)方法給了我很大的啟發(fā),在該基礎(chǔ)上,分別在第三方應(yīng)用的ActivityService中實(shí)現(xiàn)了SystemProperties屬性值的實(shí)時(shí)監(jiān)聽,app需要系統(tǒng)簽名。

注:閱讀本博客前,請(qǐng)先閱讀監(jiān)聽SystemProperties變化這篇博客。

Activity

		Parcel _data = Parcel.obtain();
        try {
            final Class<?> systemPropertyClass = Class.forName("android.os.SystemProperties");
            final Method addChangeCallback = systemPropertyClass.getDeclaredMethod(
                    "addChangeCallback", Runnable.class);
            final Method getMethod = systemPropertyClass.getDeclaredMethod(
                    "get", String.class, String.class);
            final Method setMethod = systemPropertyClass.getDeclaredMethod(
                    "set", String.class, String.class);
            addChangeCallback.invoke(null, new Runnable() {
                @Override
                public void run() {
                    Log.e("DebugUtil",  "SystemProperties change");
                    try {
                        String result = (String) getMethod.invoke(
                                null, "persist.sys.test", "77777");
                        Log.e("DebugUtil",  "SystemProperties change to " + result);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            });
            
            setMethod.invoke(null, "persist.sys.test", "88888");

            IBinder amsBinder = getService(Context.ACTIVITY_SERVICE);
            _data.writeInterfaceToken("android.app.IActivityManager");
            Boolean result = amsBinder.transact(
                    ('_'<<24)|('S'<<16)|('P'<<8)|'R'/*IBinder.SYSPROPS_TRANSACTION*/,
                    _data, null, 0);
            Log.e("DebugUtil", "result = " + result);
        } catch (RemoteException | IllegalAccessException
                | InvocationTargetException | ClassNotFoundException
                | NoSuchMethodException e) {
            e.printStackTrace();
        } finally {
            _data.recycle();
        }

Service

		try {
            Class<?> systemPropertyClass = Class.forName("android.os.SystemProperties");
            Method addChangeCallback = systemPropertyClass.getDeclaredMethod(
                    "addChangeCallback", Runnable.class);
            Method getMethod = systemPropertyClass.getDeclaredMethod(
                    "get", String.class, String.class);
            Method setMethod = systemPropertyClass.getDeclaredMethod(
                    "set", String.class, String.class);
            addChangeCallback.invoke(null, new Runnable() {
                @Override
                public void run() {
                    DebugUtil.e(TAG, "SystemProperties change");
                    try {
                        String result = (String) getMethod.invoke(null, "persist.sys.test", "123");
                        DebugUtil.e(TAG,  "SystemProperties change to " + result);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            });

            setMethod.invoke(null, "persist.sys.test", "456");

            String[] services = DeviceManagerUtil.listServices();
            if (services == null) {
                DebugUtil.e(TAG, "There are no services, how odd");
            }
            for (String service : services) {
                IBinder obj = DeviceManagerUtil.checkService(service);
                if (obj != null) {
                    Parcel data = Parcel.obtain();
                    try {
                        obj.transact(
                                ('_'<<24)|('S'<<16)|('P'<<8)|'R'/*IBinder.SYSPROPS_TRANSACTION*/,
                                data, null, 0);
                    } catch (RemoteException e) {
                        // Ignore
                    } catch (Exception e) {
                        DebugUtil.e(TAG, e.getMessage());
                    }
                    data.recycle();
                }
            }
        } catch (IllegalAccessException | InvocationTargetException
                | ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        }

DeviceManagerUtil.java

	public static String[] listServices() {
        try {
            Class<?> serviceManagerClass = Class.forName("android.os.ServiceManager");
            Method listServices = serviceManagerClass.getDeclaredMethod("listServices");
            return (String[]) listServices.invoke(null);
        } catch (ClassNotFoundException | NoSuchMethodException
                | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static IBinder checkService(String service) {
        try {
            Class<?> serviceManagerClass = Class.forName("android.os.ServiceManager");
            Method listServices = serviceManagerClass.getDeclaredMethod(
                    "checkService", String.class);
            return (IBinder) listServices.invoke(null, service);
        } catch (ClassNotFoundException | NoSuchMethodException
                | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

總結(jié)+分析

1.監(jiān)聽方需要添加回調(diào)函數(shù)
SystemProperties.addChangeCallback()設(shè)置監(jiān)聽回調(diào)函數(shù):非源碼環(huán)境下,通過反射實(shí)現(xiàn);源碼環(huán)境下,直接調(diào)用addChangeCallback()方法即可。
2.設(shè)置屬性值后,需要通知監(jiān)聽方
通知監(jiān)聽方的方式其實(shí)大同小異,遍歷所有的Activity和Service,獲取到它們的IBinder對(duì)象,調(diào)用onTransact()方法,通過Binder實(shí)現(xiàn)跨進(jìn)程通信,最終調(diào)用SystemProperties的callChangeCallbacks()方法,遍歷所有的callbacks的run()方法,通知監(jiān)聽方。
IBinder.SYSPROPS_TRANSACTION的值請(qǐng)查找自己的項(xiàng)目源碼獲取。
此處有兩點(diǎn)需要說明:一是這里涉及到的Binder原理,博主的理解程度還達(dá)不到完全講解清楚的程度(僅意會(huì)不會(huì)言傳),請(qǐng)自行查閱Binder相關(guān)原理;二是addChangeCallback()不可執(zhí)行多次,否則回調(diào)也會(huì)回調(diào)多次。

ActivityManagerService的onTransact()方法如下:

@Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
        if (code == SYSPROPS_TRANSACTION) {
            // We need to tell all apps about the system property change.
            ArrayList<IBinder> procs = new ArrayList<IBinder>();
            synchronized (this) {
                final int NP = mProcessList.mProcessNames.getMap().size();
                for (int ip = 0; ip < NP; ip++) {
                    SparseArray<ProcessRecord> apps =
                            mProcessList.mProcessNames.getMap().valueAt(ip);
                    final int NA = apps.size();
                    for (int ia = 0; ia < NA; ia++) {
                        ProcessRecord app = apps.valueAt(ia);
                        if (app.thread != null) {
                            procs.add(app.thread.asBinder());
                        }
                    }
                }
            }

            int N = procs.size();
            for (int i=0; i<N; i++) {
                Parcel data2 = Parcel.obtain();
                try {
                    procs.get(i).transact(IBinder.SYSPROPS_TRANSACTION, data2, null,
                            Binder.FLAG_ONEWAY);
                } catch (RemoteException e) {
                }
                data2.recycle();
            }
        }
        try {
            return super.onTransact(code, data, reply, flags);
        } catch (RuntimeException e) {
            // The activity manager only throws certain exceptions intentionally, so let's
            // log all others.
            if (!(e instanceof SecurityException
                    || e instanceof IllegalArgumentException
                    || e instanceof IllegalStateException)) {
            /// M: Enhance wtf excetpion @{
                if (mAmsExt.IsBuildInApp()) {
                    Slog.wtf(TAG, "Activity Manager Crash."
                        + " UID:" + Binder.getCallingUid()
                        + " PID:" + Binder.getCallingPid()
                        + " TRANS:" + code, e);
                } else {
                    Slog.e(TAG, "Activity Manager Crash."
                        + " UID:" + Binder.getCallingUid()
                        + " PID:" + Binder.getCallingPid()
                        + " TRANS:" + code, e);
                }
            /// @}
            }
            throw e;
        }
    }

SystemPropPoker.java文章來源地址http://www.zghlxwxcb.cn/news/detail-453262.html

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settingslib.development;

import android.os.AsyncTask;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

public class SystemPropPoker  {
    private static final String TAG = "SystemPropPoker";

    private static final SystemPropPoker sInstance = new SystemPropPoker();

    private boolean mBlockPokes = false;

    private SystemPropPoker() {}

    @NonNull
    public static SystemPropPoker getInstance() {
        return sInstance;
    }

    public void blockPokes() {
        mBlockPokes = true;
    }

    public void unblockPokes() {
        mBlockPokes = false;
    }

    public void poke() {
        if (!mBlockPokes) {
            createPokerTask().execute();
        }
    }

    @VisibleForTesting
    PokerTask createPokerTask() {
        return new PokerTask();
    }

    public static class PokerTask extends AsyncTask<Void, Void, Void> {

        @VisibleForTesting
        String[] listServices() {
            return ServiceManager.listServices();
        }

        @VisibleForTesting
        IBinder checkService(String service) {
            return ServiceManager.checkService(service);
        }

        @Override
        protected Void doInBackground(Void... params) {
            String[] services = listServices();
            if (services == null) {
                Log.e(TAG, "There are no services, how odd");
                return null;
            }
            for (String service : services) {
                IBinder obj = checkService(service);
                if (obj != null) {
                    Parcel data = Parcel.obtain();
                    try {
                        obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0);
                    } catch (RemoteException e) {
                        // Ignore
                    } catch (Exception e) {
                        Log.i(TAG, "Someone wrote a bad service '" + service
                                + "' that doesn't like to be poked", e);
                    }
                    data.recycle();
                }
            }
            return null;
        }
    }
}

到了這里,關(guān)于Android 如何優(yōu)雅地監(jiān)聽SystemProperties屬性值變化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • powershell 雅地關(guān)閉UDP監(jiān)聽器

    在PowerShell中優(yōu)雅地關(guān)閉UDP監(jiān)聽器意味著你需要一種機(jī)制來安全地停止正在運(yùn)行的 UdpClient 實(shí)例。由于 UdpClient 類本身沒有提供直接的停止或關(guān)閉方法,你需要通過其他方式來實(shí)現(xiàn)這一點(diǎn)。通常,這涉及到在監(jiān)聽循環(huán)中添加一個(gè)檢查點(diǎn),以便在接收到停止信號(hào)時(shí)能夠退出循環(huán)。

    2024年02月21日
    瀏覽(19)
  • Android 監(jiān)聽音頻焦點(diǎn)變化

    在 Android 中,監(jiān)聽音頻焦點(diǎn)變化意味著您可以獲得關(guān)于音頻焦點(diǎn)狀態(tài)的通知,并針對(duì)焦點(diǎn)變化執(zhí)行相應(yīng)的操作。音頻焦點(diǎn)是指哪個(gè)應(yīng)用程序或組件有權(quán)播放音頻的能力。 通過監(jiān)聽音頻焦點(diǎn)變化,您可以根據(jù)不同的焦點(diǎn)狀態(tài)進(jìn)行適當(dāng)?shù)囊纛l處理,以提供更好的用戶體驗(yàn)和避免音

    2024年04月26日
    瀏覽(43)
  • Android 監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化

    Android 監(jiān)聽網(wǎng)絡(luò)狀態(tài)變化

    此篇存在的主要意義在于解決用戶使用app中網(wǎng)絡(luò)狀態(tài)發(fā)生了變化,需要我們?nèi)?dòng)態(tài)監(jiān)聽網(wǎng)絡(luò)連接狀態(tài)(有網(wǎng)、無網(wǎng))、網(wǎng)絡(luò)類型 (包括wifi、移動(dòng)網(wǎng)絡(luò) - 3G、4G等等) 門前授課 關(guān)于網(wǎng)絡(luò)狀態(tài)的監(jiān)聽,主要是基于 Android 廣播 - BroadcaseReceiver組件 ~ 同時(shí)關(guān)于廣播的注冊(cè)方面,從An

    2024年02月10日
    瀏覽(21)
  • Android 之 監(jiān)聽 EditText 的內(nèi)容變化

    Android 之 監(jiān)聽 EditText 的內(nèi)容變化

    在前面我們已經(jīng)學(xué)過EditText控件了,本節(jié)來說下如何監(jiān)聽輸入框的內(nèi)容變化! 這個(gè)再實(shí)際開發(fā)中非常實(shí)用,另外,附帶著說下如何實(shí)現(xiàn)EditText的密碼可見與不可見! 由題可知,是基于監(jiān)聽的事件處理機(jī)制,好像前面的點(diǎn)擊事件是OnClickListener,文本內(nèi)容 變化的監(jiān)聽器則是:Te

    2024年02月12日
    瀏覽(21)
  • 微信小程序——自定義組件組件的創(chuàng)建和引用,修改組件的樣式隔離選項(xiàng),stylesolation的可選值,properties屬性,data數(shù)據(jù),methods方法,數(shù)據(jù)監(jiān)聽器,用法,監(jiān)聽對(duì)象屬性的變化

    微信小程序——自定義組件組件的創(chuàng)建和引用,修改組件的樣式隔離選項(xiàng),stylesolation的可選值,properties屬性,data數(shù)據(jù),methods方法,數(shù)據(jù)監(jiān)聽器,用法,監(jiān)聽對(duì)象屬性的變化

    ①在項(xiàng)目的根目錄中,鼠標(biāo)右鍵,創(chuàng)建 components - test 文件夾 ②在新建的 components - test 文件夾上,鼠標(biāo)右鍵,點(diǎn)擊\\\"新建 Component \\\" ③鍵入組件的名稱之后回車,會(huì)自動(dòng)生成組件對(duì)應(yīng)的4個(gè)文件,后綴名分別為 js , json ,. wxml 和. wxss 注意,為了保證目錄結(jié)構(gòu)的清晰,建議把不同的

    2024年02月15日
    瀏覽(110)
  • Android網(wǎng)絡(luò)狀態(tài)變化監(jiān)聽 -- 結(jié)合registerNetworkCallback和廣播(kotlin)

    Android網(wǎng)絡(luò)狀態(tài)變化監(jiān)聽 -- 結(jié)合registerNetworkCallback和廣播(kotlin)

    ? ? 說明 ??AndroidAndroid針對(duì)網(wǎng)絡(luò)狀態(tài)變化的監(jiān)聽,在應(yīng)用內(nèi)我們通用需要監(jiān)聽設(shè)備網(wǎng)絡(luò)狀態(tài)的變化,作出相應(yīng)的業(yè)務(wù)處理,需要一個(gè)方便的、全局的監(jiān)聽實(shí)現(xiàn)。。 ??針對(duì)不同設(shè)備的系統(tǒng)版本,使用不同的API方法實(shí)現(xiàn); ??注意使用廣播監(jiān)聽網(wǎng)絡(luò)狀態(tài)在高版本的適配問題

    2024年02月03日
    瀏覽(14)
  • nuxt3 如何監(jiān)聽路由變化?

    nuxt3 如何監(jiān)聽路由變化?

    2024年02月11日
    瀏覽(23)
  • Vue3組件不發(fā)生變化,如何監(jiān)聽pinia中數(shù)據(jù)變化?

    在開發(fā)過程中,我們需要將一些跨組件使用的的數(shù)據(jù)在pinia中進(jìn)行狀態(tài)管理,組件在初始化的時(shí)候我們能通過onMounted,computed,watch,watchEffect獲取到存儲(chǔ)在pinia state中的內(nèi)容,有一些特殊情況,在組件初始化之后我們無法通過以上四種情況獲取state中的內(nèi)容,這時(shí)候我們?cè)趺醋瞿兀?/p>

    2024年02月11日
    瀏覽(28)
  • vue2 如何監(jiān)聽數(shù)組的變化

    在Vue 2中,底層是通過重寫數(shù)組的原型方法來實(shí)現(xiàn)對(duì)數(shù)組變化的監(jiān)聽。具體來說,Vue 2使用了一個(gè)名為Observer的類來劫持?jǐn)?shù)組的原型方法,使其在調(diào)用這些方法時(shí)能夠觸發(fā)相應(yīng)的變化通知。 當(dāng)Vue 2初始化一個(gè)響應(yīng)式對(duì)象時(shí),如果對(duì)象是一個(gè)數(shù)組,Vue會(huì)將數(shù)組的原型指向一個(gè)經(jīng)過

    2024年02月12日
    瀏覽(22)
  • vue如何實(shí)現(xiàn)實(shí)時(shí)監(jiān)聽頁面寬度高度變化

    運(yùn)用的主要技術(shù):watch監(jiān)聽 話不多說直接上代碼,自行研究

    2024年02月11日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包