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

如何获取并展示UsageStats数据?如何提取应用启停时间?

How to Display App Usage & Extract Start/End Times from UsageStats

Hey there! Let's tackle your two main needs: building a clean app usage display, and pulling out individual app session start/end times from the UsageStats data you're already fetching.


1. Implementing the App Usage Display UI

A RecyclerView is perfect for showing a scrollable list of app usage details. We'll add app icons, package names, total foreground time, and last used time to each list item.

Step 1: Add Required Permissions

First, make sure you have the necessary permission in your AndroidManifest.xml (note: users need to manually enable this in Settings > Security > Apps with usage access):

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" 
    tools:ignore="ProtectedPermissions" />

Step 2: Layout for the RecyclerView

Create activity_usage_stats.xml to hold the RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/usage_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Step 3: Item Layout for Each App Entry

Make item_usage_stats.xml to display individual app details:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:orientation="horizontal"
    android:gravity="center_vertical">

    <ImageView
        android:id="@+id/app_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:marginEnd="16dp"/>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <TextView
            android:id="@+id/package_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:textStyle="bold"/>

        <TextView
            android:id="@+id/total_foreground_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="@android:color/darker_gray"/>

        <TextView
            android:id="@+id/last_used_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="@android:color/darker_gray"/>
    </LinearLayout>

</LinearLayout>

Step 4: Build the RecyclerView Adapter

Create an adapter to bind your UsageStats data to the UI:

public class UsageStatsAdapter extends RecyclerView.Adapter<UsageStatsAdapter.UsageViewHolder> {

    private List<UsageStats> mUsageStatsList;
    private PackageManager mPackageManager;

    public UsageStatsAdapter(List<UsageStats> usageStatsList, PackageManager packageManager) {
        mUsageStatsList = usageStatsList;
        mPackageManager = packageManager;
    }

    @NonNull
    @Override
    public UsageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_usage_stats, parent, false);
        return new UsageViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull UsageViewHolder holder, int position) {
        UsageStats stats = mUsageStatsList.get(position);
        String packageName = stats.getPackageName();

        // Set package name
        holder.packageNameTextView.setText(packageName);

        // Format total foreground time (ms to hh:mm:ss)
        String totalTime = formatMillisToTime(stats.getTotalTimeInForeground());
        holder.totalForegroundTimeTextView.setText("Total Foreground Time: " + totalTime);

        // Format last used time
        String lastUsed = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
                .format(new Date(stats.getLastTimeUsed()));
        holder.lastUsedTimeTextView.setText("Last Used: " + lastUsed);

        // Load app icon
        try {
            Drawable appIcon = mPackageManager.getApplicationIcon(packageName);
            holder.appIconImageView.setImageDrawable(appIcon);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            holder.appIconImageView.setImageResource(R.drawable.ic_default_app);
        }
    }

    @Override
    public int getItemCount() {
        return mUsageStatsList.size();
    }

    public static class UsageViewHolder extends RecyclerView.ViewHolder {
        ImageView appIconImageView;
        TextView packageNameTextView;
        TextView totalForegroundTimeTextView;
        TextView lastUsedTimeTextView;

        public UsageViewHolder(@NonNull View itemView) {
            super(itemView);
            appIconImageView = itemView.findViewById(R.id.app_icon);
            packageNameTextView = itemView.findViewById(R.id.package_name);
            totalForegroundTimeTextView = itemView.findViewById(R.id.total_foreground_time);
            lastUsedTimeTextView = itemView.findViewById(R.id.last_used_time);
        }
    }

    // Helper to convert milliseconds to readable time
    private String formatMillisToTime(long millis) {
        long seconds = millis / 1000;
        long minutes = seconds / 60;
        long hours = minutes / 60;
        seconds = seconds % 60;
        minutes = minutes % 60;
        return String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes, seconds);
    }
}

Step 5: Bind Data to RecyclerView in Your Activity

Update your existing code to connect the stats list to the RecyclerView:

// After fetching the stats list
RecyclerView recyclerView = findViewById(R.id.usage_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
UsageStatsAdapter adapter = new UsageStatsAdapter(stats, getPackageManager());
recyclerView.setAdapter(adapter);

2. Extracting App Start & End Times

Important note: queryUsageStats() returns aggregated data (like total foreground time for the period). To get individual app session start/end times, you need to use UsageEvents—it tracks every foreground/background transition.

Step 1: Query UsageEvents

Add this code to fetch events for your time range:

UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -1);
long start = calendar.getTimeInMillis();
long end = System.currentTimeMillis();

// Fetch all usage events in the time range
UsageEvents events = usageStatsManager.queryEvents(start, end);

Step 2: Process Events to Capture Sessions

Track when apps move to foreground (start) and background (end):

// Track apps currently in foreground
Map<String, Long> currentForegroundApps = new HashMap<>();
// Store all app sessions (create a model class for this)
List<AppSession> appSessions = new ArrayList<>();

UsageEvents.Event event = new UsageEvents.Event();
while (events.hasNextEvent()) {
    events.getNextEvent(event);

    switch (event.getEventType()) {
        case UsageEvents.Event.MOVE_TO_FOREGROUND:
            // App started - record start time
            currentForegroundApps.put(event.getPackageName(), event.getTimeStamp());
            break;
        case UsageEvents.Event.MOVE_TO_BACKGROUND:
            // App closed - calculate session duration
            Long startTime = currentForegroundApps.remove(event.getPackageName());
            if (startTime != null) {
                long endTime = event.getTimeStamp();
                appSessions.add(new AppSession(event.getPackageName(), startTime, endTime));
            }
            break;
    }
}

// Handle apps still in foreground at the end of the period
for (Map.Entry<String, Long> entry : currentForegroundApps.entrySet()) {
    appSessions.add(new AppSession(entry.getKey(), entry.getValue(), end));
}

Step 3: Create an AppSession Model

Store session data neatly with this class:

public class AppSession {
    private String packageName;
    private long startTime;
    private long endTime;

    public AppSession(String packageName, long startTime, long endTime) {
        this.packageName = packageName;
        this.startTime = startTime;
        this.endTime = endTime;
    }

    // Getters for session data
    public String getPackageName() { return packageName; }
    public long getStartTime() { return startTime; }
    public long getEndTime() { return endTime; }
    public long getDuration() { return endTime - startTime; }
}

Now you can use the appSessions list to display individual start/end times, just like you did with the aggregated stats!


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:45:13