2017-08-12 57 views
13

在我的应用中,多个App Widgets可以放置在主屏幕上,每个小部件定期获取远程数据。分别跟踪多个应用小部件的数据使用情况

我的目标是:与各多个小部件的相关分开

  • WiFi和移动数据使用量
  • 自己的应用程序的
  • 只(在其他应用程序的数据使用不感兴趣)

    • 跟踪数据使用
    • 没有额外的权限
    • 允许小部件同时执行网络操作而不重复计算数据使用率
    • 包括WebView活动数据使用来自小部件中发起
    • 报告结果应用程序内(不只是当拴在网络通信工具)

    这是很容易的登录数据使用你自己的UID前,一个小部件后通过使用getUidRxBytes()getUidTxBytes()(通过您自己的应用程序的UID)更新为TrafficStats,然后采取差异。虽然这种粗糙和准备的方法在小部件串联运行时给出了明智的价值,但是当它们同时运行时,不可避免地会出现一定程度的双重(三重等)计数。

    我宁愿不强制小部件进行系列更新,因为我宁愿让设备的作业调度引擎找出最好的方法。所以我需要一种方法来将每个小部件的数据使用分开。

    似乎标签的使用可能是...的方式标记网络运营的appWidgetId,然后过滤基于这个appWidgetId统计。我不相信这种方法实际上使一个小部件的数据使用与另一个小部件区分开来(也许这些存储桶会变得混乱),但事实是我无法让标签工作,所以我不能但告诉。

    在网络操作开始之前,您可以使用setThreadStatsTag(tag)设置标记,但在TrafficStats类中看不到任何用于检索按标记过滤的结果的方法。 有谁知道有什么不同?

    所以我再看看NetworkStatsManager,特别是NetworkStatsManager.queryDetailsForUidTag(... , tag)。这似乎允许你基于特定的tag进行过滤,并且没有任何额外的权限(对于你自己的应用程序的UID),这是很好的。但是我不能用这种方法返回任何带有数据的桶,尽管在使用HttpURLConnection的网络操作之前​​设置了TrafficStats.setThreadStatsTag(appWidgetId),并且之后通过调用NetworkStatsManager.queryDetailsForUidTag(... , appWidgetId)用相同的标签查询。

    在另一方面,NetworkStatsManager.queryDetailsForUid()(无tag参数)确实有效的数据返回水桶,所以它似乎只是不工作,而不是什么我做错了与NetworkStatsManager每根本的标签SE。

    我设定的标签:

    @Override 
    protected void onPreExecute() { 
        TrafficStats.setThreadStatsTag(appWidgetId); 
    } 
    
    @Override 
    protected Bitmap doInBackground(String... baseUrls) { 
        // fetch data with HttpURLConnection 
    } 
    
    @Override 
    protected void onPostExecute(Bitmap bmp) { 
        TrafficStats.clearThreadStatsTag(); 
    } 
    

    和(对于WiFi数据),我查询与统计:

    void networkStatsStuff() { 
        NetworkStats networkStats; 
        NetworkStats networkStatsTagged; 
        int networkType = ConnectivityManager.TYPE_WIFI; 
    
        try { 
         networkStats = networkStatsManager.queryDetailsForUid(networkType, "", startTime, endTime, myUid); 
        } catch (RemoteException e) { 
         return; 
        } 
    
        networkStatsTagged = networkStatsManager.queryDetailsForUidTag(networkType, "", startTime, endTime, myUid, appWidgetId); 
    
        long totalData = getTotalData(networkStats); 
        long totalDataTagged = getTotalData(networkStatsTagged); 
    
        Log.d(TAG, "totalData: " + totalData);    // this seems to work 
        Log.d(TAG, "totalDataTagged: " + totalDataTagged); // this is always zero 
    } 
    
    long getTotalData(NetworkStats networkStats) { 
        long totalData = 0; 
        do { 
         NetworkStats.Bucket bucket = new NetworkStats.Bucket(); 
         networkStats.getNextBucket(bucket); 
         totalData = totalData + bucket.getRxBytes() + bucket.getTxBytes(); 
    
        } while (networkStats.hasNextBucket()); 
        return totalData; 
    } 
    

    我在做什么错? (编辑:部分答案在下面)或者也许有一种完全不同的方式来实现我的目标?

  • 回答

    1

    部分答案:

    所以我觉得我被this guide带坏了,这是我得到的setThreadStatsTag()clearThreadStatsTag(),放置在preExecute()postExecute()分别AsyncTask的。

    当我将标记的设置和取消设置移动到AsyncTaskdoInBackground()部分时,我开始看到标记...我首先在Android设备监视器中注意到了这一点,但它们在使用NetworkStats通过tag过滤的方法。

    所以它似乎更正确使用类似描述in this guide,沿着线:

    @Override 
    protected Bitmap doInBackground(String... baseUrls) { 
        TrafficStats.setThreadStatsTag(appWidgetId); 
        try { 
         // fetch data with HttpURLConnection 
        } finally { 
         TrafficStats.clearThreadStatsTag(); 
        } 
    } 
    

    所以是第一指导只是简单的错误?

    仍然没有得到解决:

    • 查询流动数据用量无需任何额外的权限(我担心READ_PHONE_STATE权限是必需的...好像矫枉过正,和恼人考虑到许可不需要与TrafficStats方法也读取移动数据使用,尽管与其他接口一起)
    • 包括数据用量高于WebView(同样,我担心这是不可能的,即不可能在WebView中标记流量并因此不可能区分通过标签仅仅是因为有关协议的性质... thisthis可能是相关的)
    相关问题