我有一个简单的活动,需要活动10-15分钟。该活动使用TelephonyManager获取三个LTE参数:RSRP,RSRQ,PCI。它每秒收集这三个参数和一个时间戳,因此,UI每秒更新一次。
用于获取LTE参数的方法在后台线程上运行。除了UI每秒更新一次,没有什么是计算密集型的。但是,如果我运行活动超过五分钟,那么我会收到可爱的Android Monitor消息:" I / Choreographer:跳过91帧!应用程序可能在其主线程上做了太多工作。"
所以我必须做错事,因为我相信我在后台线程上做了所有艰苦的工作。如果我运行活动10-15分钟,它将跳过约1,000帧。然后,如果我通过应用程序并按下按钮运行另一个测试,它将开始跳过与前15分钟测试结束时一样多的帧,并且在第二个测试结束时它可以跳过多达2500个帧。然后每次按下按钮开始下一个活动时需要更长更长的时间(即使在没有完成任何操作的活动中)。而且只有五项活动!
以下是我需要在15分钟内有效收集数据的活动的屏幕截图:
以下是我的名为Third.java的活动代码:
package com.parksjg.its.pscrindoortesttool;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.CellInfo;
import android.telephony.CellInfoLte;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import au.com.bytecode.opencsv.CSVWriter;
/**
* Created by josephparks on 1/27/16.
*/
public class Third extends Activity implements Runnable {
SignalStrengthListener signalStrengthListener;
TextView lteRsrp;
TextView lteRsrq;
TextView cellPciTextView, fileName;
ImageView img;
Button stopButton;
TelephonyManager tm;
List<CellInfo> cellInfoList;
String lte1, lte2;
int cellPci = 0;
ArrayList data;
CSVWriter writer;
String mydate;
String startDate;
boolean done = false;
@Override
public void run() {
// Moves the current Thread into the background
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
// This runs the code to grab the LTE parameters
startTele();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.third_activity);
// Sets up the TextViews and UI
setupUI();
// Runs telephony method on background thread
run();
// takes the collected data and adds it to the CSV format once per second
setupCSV();
// Sets up the stop button, writes data to CSV, and starts next activity
setupButton();
}
// This method is called by startTele() and is responsible for grabbing the LTE params
private class SignalStrengthListener extends PhoneStateListener {
@Override
public void onSignalStrengthsChanged(android.telephony.SignalStrength signalStrength) {
((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(signalStrengthListener, SignalStrengthListener.LISTEN_SIGNAL_STRENGTHS);
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String ltestr = signalStrength.toString();
String[] parts = ltestr.split(" ");
lte1 = parts[9];
lte2 = parts[10];
try {
cellInfoList = tm.getAllCellInfo();
for (CellInfo cellInfo : cellInfoList) {
if (cellInfo instanceof CellInfoLte) {
// cast to CellInfoLte and call all the CellInfoLte methods you need
// Gets the LTE PCI: (returns Physical Cell Id 0..503, Integer.MAX_VALUE if unknown)
cellPci = ((CellInfoLte) cellInfo).getCellIdentity().getPci();
}
}
} catch (Exception e) {
// Log.d("SignalStrength", "+++++++++++++++++++++++++++++++ null array spot 3: " + e);
}
// Gets the timestamp of when these LTE params where collected
mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
// Updates the UI TextViews for RSRP, RSRQ, and PCI
lteRsrp.setText(String.valueOf(lte1));
lteRsrq.setText(String.valueOf(lte2));
cellPciTextView.setText(String.valueOf(cellPci));
super.onSignalStrengthsChanged(signalStrength);
}
}
// This takes the collected LTE data and timestamps and concatenates them into one object
// which is then easy to create a CSV file from
private void setupCSV() {
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
data.add(new String[]{mydate, lte1, lte2, String.valueOf(cellPci)});
}
}, 0, 1000);//put here time 1000 milliseconds=1 second
}
private void setupUI () {
data = new ArrayList();
// startDate is used to name the CSV file
startDate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
lteRsrp = (TextView) findViewById(R.id.lteRsrp);
lteRsrq = (TextView) findViewById(R.id.lteRsrq);
cellPciTextView = (TextView) findViewById(R.id.cellPciTextView);
fileName = (TextView) findViewById(R.id.fileName);
fileName.setText(startDate);
stopButton = (Button) findViewById(R.id.stopButton);
img = (ImageView) findViewById(R.id.imageView);
img.setImageResource(R.drawable.recording);
// Log.d("Time and Date", "+++++++++++++ DATE : " + mydate);
}
private void startTele() {
// start the signal strength listener
signalStrengthListener = new SignalStrengthListener();
((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(signalStrengthListener, SignalStrengthListener.LISTEN_SIGNAL_STRENGTHS);
tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
try {
cellInfoList = tm.getAllCellInfo();
} catch (Exception e) {
// Log.d("SignalStrength", "+++++++++++++++++++++++++++++++++++++++++ null array spot 1: " + e);
}
}
private void setupButton() {
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(Third.this, "Writing output to CSV!", Toast.LENGTH_LONG).show();
// Writes the data to a CSV file named by startDate
writeCSV();
try{
if(signalStrengthListener != null) {
tm.listen(signalStrengthListener, SignalStrengthListener.LISTEN_NONE);
// Log.d("TAG", "+++++++++++++++++++++++++++++++++++ Stop button Success!!!!!!");
}
}catch(Exception e){
e.printStackTrace();
// Log.d("TAG", "+++++++++++++++++++++++++++++++++++ Stop button Fail!!!!!! with error = " + e);
}
// Intent passes startDate and the boolean done to indicate when the CSV has been written
Intent intent = new Intent(getBaseContext(), Fourth.class);
intent.putExtra("START_DATE", startDate);
intent.putExtra("DONE", done);
startActivity(intent);
finish();
}
});
}
private void writeCSV() {
try {
File file = new File(getExternalFilesDir(null), startDate+".csv");
writer = new CSVWriter(new FileWriter(file, true), ',');
// Headers
String[] headers = "Time, RSRP, RSRQ, PCI".split(",");
writer.writeNext(headers);
writer.writeAll(data);
writer.flush();
writer.close();
Toast.makeText(Third.this, "CSV Successful!", Toast.LENGTH_SHORT).show();
done = true;
// Log.d("CSV Writer", "CSV Writer Successful!");
} catch (IOException e) {
// Log.d("CSV Writer", "Error writing CSV file : " + e);
Toast.makeText(Third.this, "Error writing CSV file", Toast.LENGTH_SHORT).show();
}
}
}
以下是名为third_activity.xml的相应XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffdc1d">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Recording"
android:textSize="26sp"
android:textColor="#000000"
android:id="@+id/lteRecording"
android:layout_alignParentTop="true"
android:textAlignment="center"
android:background="#f91616"
android:textStyle="bold"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:paddingTop="10dp"
android:paddingBottom="10dp" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textSize="22sp"
android:textColor="#000000"
android:id="@+id/lteRsrp"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_marginStart="29dp"
android:layout_marginTop="120dp"
android:textAlignment="textEnd"
android:background="#ffdc1d"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE RSRP"
android:textSize="22sp"
android:textColor="#000000"
android:id="@+id/textView2"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_alignTop="@+id/lteRsrp"
android:layout_toEndOf="@+id/stopButton" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textColor="#a71b1b"
android:textSize="22sp"
android:id="@+id/lteRsrq"
android:layout_below="@+id/lteRsrp"
android:layout_alignStart="@+id/lteRsrp"
android:textAlignment="textEnd"
android:textStyle="bold"
android:background="#ffdc1d"
android:layout_marginTop="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE RSRQ"
android:textSize="22sp"
android:textColor="#a71b1b"
android:id="@+id/textView3"
android:layout_below="@+id/textView2"
android:layout_alignStart="@+id/textView2"
android:textStyle="bold"
android:background="#ffdc1d"
android:layout_marginTop="20dp" />
<TextView
android:layout_width="210dp"
android:layout_height="wrap_content"
android:text="0"
android:textSize="22sp"
android:textColor="#075f09"
android:id="@+id/cellPciTextView"
android:layout_below="@+id/lteRsrq"
android:layout_alignStart="@+id/lteRsrq"
android:textAlignment="textEnd"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_marginTop="20dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="= LTE PCI"
android:textSize="22sp"
android:textColor="#075f09"
android:id="@+id/textView4"
android:layout_below="@+id/textView3"
android:layout_alignStart="@+id/textView3"
android:background="#ffdc1d"
android:textStyle="bold"
android:layout_marginTop="20dp" />
<Button
android:layout_width="120dp"
android:layout_height="wrap_content"
android:text="Stop"
android:textSize="22sp"
android:textColor="#ffdc1d"
android:id="@+id/stopButton"
android:background="#f91616"
android:textStyle="bold"
android:padding="4dp"
android:textAlignment="center"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="41dp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:src="@drawable/recording"
android:layout_above="@+id/textView2"
android:layout_alignStart="@+id/lteRsrp"
android:layout_marginBottom="10dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Filename:"
android:textColor="#000000"
android:textSize="26sp"
android:id="@+id/textView6"
android:layout_marginTop="50dp"
android:layout_below="@+id/cellPciTextView"
android:layout_alignStart="@+id/cellPciTextView"
android:textStyle="bold|italic" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="#000000"
android:textSize="26sp"
android:id="@+id/fileName"
android:layout_below="@+id/textView6"
android:layout_centerHorizontal="true"
android:textStyle="bold" />
</RelativeLayout>
这是AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.parksjg.its.pscrindoortesttool" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".First"
android:screenOrientation="portrait"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Second"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
<activity android:name=".Third"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
<activity android:name=".Fourth"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
<activity android:name=".Final"
android:screenOrientation="portrait"
android:noHistory="true">
</activity>
</application>
</manifest>
我是否在后台线程中执行了错误的代码?如何让这个运行更顺畅,更敏感?再次,它在5分钟内运行时速度很快,但是我们用它来测试研究室内LTE网络,我们的步测/驱动测试需要10-15分钟,但是当我按下停止按钮或新测试按钮时需要它在一两秒内作出回应。有时按下按钮后动作生效需要20-30秒,特别是在连续测试后。
以下是该应用的完整流程:
上一个活动的按钮重新启动第二个活动。如果您需要任何其他代码,请告诉我,如果有人对自己运行代码感兴趣,我也可以在GitHub上发布整个AndroidStudio项目。
谢谢!
答案 0 :(得分:1)
由于它是随着时间的推移构建的,它可能意味着操作系统没有正确地对视图或对象进行垃圾收集,因为它们的引用没有被释放......这会导致内存问题。我建议第一步使用内存分析器并检查在测试期间使用了多少内存。除此之外,你可以通过做这样的事情来检查你的方法需要执行的时间
void methodName(){
long startTime = System.currentTimeMillis();
.
.
.
.
Log.w("time needed for this method",Long.toString(System.currentTimeMillis()-startTime);
}