44

我试图在每个应用程序的基础上找出 Android 上的数据使用情况。Android 数据使用应用程序和配额/上限监视器小部件之类的东西:永远不会为数据收取额外费用或再次获得上限!.

我查看了 Stack Overflow 问题How to go about detection data usage in the Android environment

但这并没有太大帮助。


ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo( mInfo );
List<RunningAppProcessInfo> listOfRunningProcess = activityManager.getRunningAppProcesses();
Log.d(TAG, "XXSize: " + listOfRunningProcess.size());

for (RunningAppProcessInfo runningAppProcessInfo : listOfRunningProcess) {

    if (runningAppProcessInfo.uid > 1026)
    {
        Log.d(TAG, "ANS " + runningAppProcessInfo.processName +
                   " Id :" + runningAppProcessInfo.pid +
                   " UID: " + runningAppProcessInfo.uid);
    }
}

我按照Akos Cz的建议尝试了上述代码。但是,与您上面提到的不同,所有UID都是数字。app_79这可以吗?

4

7 回答 7

44

以下链接应该可以帮助您了解如何以编程方式确定每个应用程序的数据使用情况。

您将需要实现您的代码以使用TraficStats API 并跟踪每个 UID(应用程序)发送/接收的字节数。

于 2012-08-13T18:31:27.687 回答
10

在创建新类 PackageInformationTotal 后使用此方法。

public void getPakagesInfoUsingHashMap() {
    final PackageManager pm = getPackageManager();
    // get a list of installed apps.
    List<ApplicationInfo> packages = pm.getInstalledApplications(0);

    // loop through the list of installed packages and see if the selected
    // app is in the list
    for (ApplicationInfo packageInfo : packages) {
        // get the UID for the selected app
        UID = packageInfo.uid;
        String package_name = packageInfo.packageName;
        ApplicationInfo app = null;
        try {
            app = pm.getApplicationInfo(package_name, 0);
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String name = (String) pm.getApplicationLabel(app);
        Drawable icon = pm.getApplicationIcon(app);
        // internet usage for particular app(sent and received)
        double received = (double) TrafficStats.getUidRxBytes(UID)

                / (1024 * 1024);
        double send = (double) TrafficStats.getUidTxBytes(UID)
                / (1024 * 1024);
        double total = received + send;

        if(total>0)
        {
            PackageInformationTotal pi=new PackageInformationTotal();
            pi.name=name;
            pi.packageName=package_name;
            pi.icon=icon;               
            pi.totalMB=String.format( "%.2f", total )+" MB";
            pi.individual_mb=String.format( "%.2f", total );
            totalData+=Double.parseDouble(String.format( "%.2f", total ));
            dataHash.add(pi);
        Log.e(name,String.format( "%.2f", total )+" MB");
        }

    }
    Editor edit=shared.edit();
    edit.putString("Total",String.format( "%.2f", totalData));
    edit.commit();
}

之后,您可以以 MB 为单位跟踪所有进程使用情况。

于 2014-03-21T13:44:30.200 回答
1

程序上:

您可以为操作声明意图过滤器ACTION_MANAGE_NETWORK_USAGE(在 Android 4.0 中引入),以表明您的应用程序定义了一个提供选项来控制数据使用的活动。ACTION_MANAGE_NETWORK_USAGE显示用于管理特定应用程序的网络数据使用的设置。当您的应用具有允许用户控制网络使用的设置活动时,您应该为该活动声明此意图过滤器。查看此内容以获取有关管理数据使用管理每个应用程序使用的更多信息。

的正确定义ACTION_MANAGE_NETWORK_USAGE可以在这里看到。

于 2012-08-13T18:34:09.387 回答
0

此代码段也适用于您设备中实际运行的应用程序

final PackageManager pm = getPackageManager();

ActivityManager activityManager = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
//final List<ActivityManager.RunningTaskInfo> recentTasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (int i = 0; i < appProcesses.size(); i++) {
    Log.d("Executed app", "Application executed : " + appProcesses.get(i).processName + "\t\t ID: " + appProcesses.get(i).pid + "");
    //  String packageName = activityManager.getRunningTasks(1).get(0).topActivity.getPackageName();
    //String packageName = appProcesses.get(i)..getPackageName();
    ApplicationInfo app = null;
    try {
        app = pm.getApplicationInfo(appProcesses.get(i).processName, 0);
        if ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 1) {
            //it's a system app, not interested
        } else if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
            //Discard this one
            //in this case, it should be a user-installed app
        } else {
            // tx = TrafficStats.getUidTxBytes(app.uid);
            //rx = TrafficStats.getUidRxBytes(app.uid);
            long delta_rx = TrafficStats.getUidRxBytes(app.uid) - rx;

            long delta_tx = TrafficStats.getUidTxBytes(app.uid) - tx;
        }
    }
于 2015-09-05T12:16:40.910 回答
0
 public class Main extends Activity {

    private Handler mHandler = new Handler();
    private long mStartRX = 0;
    private long mStartTX = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mStartRX = TrafficStats.getTotalRxBytes();
        mStartTX = TrafficStats.getTotalTxBytes();
        if (mStartRX == TrafficStats.UNSUPPORTED || mStartTX == TrafficStats.UNSUPPORTED) {
            AlertDialog.Builder alert = new AlertDialog.Builder(this);
            alert.setTitle("Uh Oh!");
            alert.setMessage("Your device does not support traffic stat monitoring.");
            alert.show();
        } else {
            mHandler.postDelayed(mRunnable, 1000);
        }
    }

    private final Runnable mRunnable = new Runnable() {
        public void run() {
            TextView RX = (TextView)findViewById(R.id.RX);
            TextView TX = (TextView)findViewById(R.id.TX);
            long rxBytes = TrafficStats.getTotalRxBytes()- mStartRX;
            RX.setText(Long.toString(rxBytes));
            long txBytes = TrafficStats.getTotalTxBytes()- mStartTX;
            TX.setText(Long.toString(txBytes));
            mHandler.postDelayed(mRunnable, 1000);
        }
     };
}

您还可以查看https://github.com/commonsguy/cw-andtuning/tree/master/TrafficMonitor

于 2016-03-04T06:21:12.530 回答
0

要访问单个应用程序的统计信息,您需要该应用程序的 uid,它是系统在安装时分配给每个应用程序的 int 值。

PackageManager packageManager = context.getPackageManager();

ApplicationInfo info = packageManager.getApplicationInfo("com.example.app", 0); 

int packageUid = info.uid;

要为 package 获取 Mobile 的所有 Rx 和 Tx 字节:

NetworkStats.Bucket bucket = networkStatsManager.queryDetailsForUid(ConnectivityManager.TYPE_MOBILE, getSubscriberId(context, ConnectivityManager.TYPE_MOBILE), 0, System.currentTimeMillis(),packageUid);
            
            
    
long rxBytes = 0L;
           
long txBytes = 0L;
            
NetworkStats.Bucket bucket = new NetworkStats.Bucket();
           
while (networkStats.hasNextBucket()) {
            
     networkStats.getNextBucket(bucket);
     rxBytes += bucket.getRxBytes();
     txBytes += bucket.getTxBytes(); 
}
networkStats.close();

有关这方面的更多说明,请查看: 如何以编程方式显示所有应用程序的数据使用情况?

于 2020-08-26T12:25:12.087 回答
-1

经过长时间的努力,我能够找到通过任何接口为每个已安装应用程序在 android 设备中获取数据的解决方案。

由于 Android 提供了 TrafficStats API,但这些 API 为每个应用程序 uid 提供了完整的数据统计信息,因为设备启动并且甚至 API 不支持通过特定应用程序的任何接口获取数据。即使我们依赖 TraffiucStates APIS,我们也会为每个应用程序获得一个新的数据统计信息。

所以我想使用隐藏的 API 来使用这个..

在这里,我提到了通过 Android 中的任何接口获取每个应用程序的数据统计信息的步骤...

  1. 建立“INetworkStatsSession”会话

    #import android.net.INetworkStatsSession;

INetworkStatsSession mStatsSession = mStatsService.openSession();

  1. 根据您要测量的接口创建一个网络模板..

    #import static android.net.NetworkTemplate.buildTemplateEthernet;
    #import static android.net.NetworkTemplate.buildTemplateMobile3gLower;
    #import static android.net.NetworkTemplate.buildTemplateMobile4g;
    #import static android.net.NetworkTemplate.buildTemplateMobileAll;
    #import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
    
    #import android.net.NetworkTemplate;
    
    private NetworkTemplate mTemplate;
    
    mTemplate = buildTemplateMobileAll(getActiveSubscriberId(this
                    .getApplicationContext()));
    
  2. 获取活动订阅者 ID:

    private static String getActiveSubscriberId(Context context) {
        final TelephonyManager tele = TelephonyManager.from(context);
        final String actualSubscriberId = tele.getSubscriberId();
        return SystemProperties.get(TEST_SUBSCRIBER_PROP, actualSubscriberId);
    }
    
  3. 通过传递应用程序 UID 收集各个应用程序的网络历史记录...

     private NetworkStatsHistory collectHistoryForUid(NetworkTemplate template,
            int uid, int set) throws RemoteException {
        final NetworkStatsHistory history = mStatsSession.getHistoryForUid(
                template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
        return history;
    
    }
    
  4. 获取总消费数据:

    public void showConsuption(int UID){
        NetworkStatsHistory history = collectHistoryForUid(mTemplate, UID,
                SET_DEFAULT);
    
        Log.i(DEBUG_TAG, "load:::::SET_DEFAULT:.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
    
        history = collectHistoryForUid(mTemplate, 10093,
                SET_FOREGROUND);
        Log.i(DEBUG_TAG, "load::::SET_FOREGROUND::.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
    
        history = collectHistoryForUid(mTemplate, 10093,
                SET_ALL);
        Log.i(DEBUG_TAG, "load::::SET_ALL::.getTotalBytes:"+ Formatter.formatFileSize(context, history.getTotalBytes()));
    
    }
    
于 2015-04-20T11:56:05.237 回答