[英]Android App Skips Frames, crashes after a while
我之前曾发布过有关我的应用跳过帧的信息,因为我可能没有进行后台活动并无法正确更新UI,这是问题的链接: 在其他UI上执行后台操作
我使用了AsyncTask,Handlers,Timer,Threads ...我仍然收到与应用程序跳过帧相同的错误。
这是我的完整代码:
public class MainActivity extends Activity {
public static final String DEBUG_TAG = "MainActvity";
public int mInterval = 5000; // 10 seconds by default, can be changed here, it should be aligned
// with how many secs in takes to get latency packets
private NetworkInformation dsNetwork;
private TextView wifiTextView;
private TextView ipTextView;
private TextView macTextView;
private TextView ssidTextView;
private TextView linkSpeedTextView;
private TextView frequencyTextView;
private TextView signalLevelTextView;
private TextView dlBandwidthTextView;
private TextView upBandwidthTextView;
private TextView latencyTextView;
private Handler handler;
//private Runnable runnableCode;
//private Timer timerAsync;
//private TimerTask timerTaskAsync;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
wifiTextView = (TextView)findViewById(R.id.wifi_textView);
ipTextView = (TextView)findViewById(R.id.ip_val_textView);
macTextView = (TextView)findViewById(R.id.mac_val_textView);
ssidTextView = (TextView)findViewById(R.id.ssid_val_textView);
linkSpeedTextView = (TextView)findViewById(R.id.linkSpeed_val_textView);
frequencyTextView = (TextView)findViewById(R.id.frequency_val_textView);
signalLevelTextView = (TextView)findViewById(R.id.signalLevel_val_textView);
dlBandwidthTextView = (TextView)findViewById(R.id.dlBandwidth_val_textView);
upBandwidthTextView = (TextView)findViewById(R.id.upBandwidth_val_textView);
latencyTextView = (TextView)findViewById(R.id.latency_val_textView);
handler = new Handler();
startRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
@Override
public void run() {
updateUI(dsNetwork); //this function can change value of mInterval.
handler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
dsNetwork = new NetworkInformation(getApplicationContext());
mStatusChecker.run();
}
void stopRepeatingTask() {
handler.removeCallbacks(mStatusChecker);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateUI(NetworkInformation dsNetwork){
// Handles updating the textviews in the UI
//Log.d(DEBUG_TAG, "updateUI(NetworkInformation)");
if (dsNetwork.isConnected()){
wifiTextView.setText(R.string.wifi_is_on);
wifiTextView.setTextColor(Color.GREEN);
ipTextView.setText(dsNetwork.getIpAddress());
macTextView.setText(dsNetwork.getMacAddress());
ssidTextView.setText(dsNetwork.getSsid());
linkSpeedTextView.setText(String.valueOf(dsNetwork.getLinkSpeed()) + " Mbps");
frequencyTextView.setText(String.valueOf(dsNetwork.getFrequency()) + " MHz");
signalLevelTextView.setText(String.valueOf(dsNetwork.getSignalLevel()) + "%");
dlBandwidthTextView.setText(String.valueOf(dsNetwork.getDlBandwidth()/1000) + " Mbps");
upBandwidthTextView.setText(String.valueOf(dsNetwork.getDlBandwidth()/1000) + " Mbps");
latencyTextView.setText(String.valueOf(dsNetwork.getLatency("10.10.0.62")) + " ms");
}
else {
wifiTextView.setText(R.string.wifi_is_off);
wifiTextView.setTextColor(Color.RED);
ipTextView.setText("N/A");
macTextView.setText("N/A");
ssidTextView.setText("N/A");
linkSpeedTextView.setText("N/A");
frequencyTextView.setText("N/A");
signalLevelTextView.setText("N/A");
dlBandwidthTextView.setText("N/A");
upBandwidthTextView.setText("N/A");
latencyTextView.setText("N/A");
}
}
}
这是处理获取信息的网络类:
public class NetworkInformation {
public static int SIGNAL_LEVEL_LIMIT = 101;
public Context mContext;
public static String DEBUG_TAG = "NetworkInformation";
private boolean isConnected;
private String networkType; //Wifi, Mobile Data, Ethernet...
private String ssid;
private String ipAddress;
private String macAddress;
private int frequency; // in MHz
private int linkSpeed; // in Mbps
private int signalLevel; // Measured from 1 to SIGNAL_LEVEL_LIMIT
private int dlBandwidth; // downstream bandwidth in Kbps
private int upBandwidth; // upstream bandwidth in Kbps
public boolean isConnected() {
return isConnected;
}
public String getNetworkType() {
return networkType;
}
public String getSsid() {
return ssid;
}
public int getFrequency() {
return frequency;
}
public String getIpAddress() {
return ipAddress;
}
public String getMacAddress() {
return macAddress;
}
public int getLinkSpeed() {
return linkSpeed;
}
public int getSignalLevel() {
return signalLevel;
}
public int getDlBandwidth() {
return dlBandwidth;
}
public int getUpBandwidth() {
return upBandwidth;
}
// Constructor: gets application contex, sets whether or not there is connection, and sets the
// connection-related variables
public NetworkInformation(Context mContext) {
this.mContext = mContext;
setConnectionStatus();
setNetworkType();
if (this.networkType == "None") {
// TODO: handle the case when there's no connection
}
if (this.networkType == "Wifi") {
setWifiInfo();
}
if(this.networkType == "Mobile Data") {
//TODO: setMobileDataInfo()
}
}
/*
Returns the latency to a given server in mili-seconds by issuing a ping command.
system will issue 5 ICMP Echo Request packet each having size of 56 bytes
every second, and returns the avg latency of them.
Returns 0 when there is no connection
*/
public double getLatency(String ipAddress){
String pingCommand = "/system/bin/ping -c 4 " + ipAddress;
String inputLine = "";
double avgRtt = 0;
try {
// execute the command on the environment interface
Process process = Runtime.getRuntime().exec(pingCommand);
// gets the input stream to get the output of the executed command
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
inputLine = bufferedReader.readLine();
while ((inputLine != null)) {
if (inputLine.length() > 0 && inputLine.contains("avg")) { // when we get to the last line of executed ping command
break;
}
inputLine = bufferedReader.readLine();
}
}
catch (IOException e){
Log.v(DEBUG_TAG, "getLatency: EXCEPTION");
e.printStackTrace();
}
// Extracting the average round trip time from the inputLine string
String afterEqual = inputLine.substring(inputLine.indexOf("="), inputLine.length()).trim();
String afterFirstSlash = afterEqual.substring(afterEqual.indexOf('/') + 1, afterEqual.length()).trim();
String strAvgRtt = afterFirstSlash.substring(0, afterFirstSlash.indexOf('/'));
avgRtt = Double.valueOf(strAvgRtt);
return avgRtt;
}
/*
The following are private utility functions
*/
// Checks if the device is connected to the Internet, and sets the class variables
private void setConnectionStatus() {
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
// if there is internet connection, set the variabel
if ((activeNetwork != null) && (activeNetwork.isConnectedOrConnecting()))
this.isConnected = true;
else
this.isConnected = false;
}
// Returns the type of network: Internet, Mobile Data, WiMax...
private void setNetworkType() {
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
String networkType = "None";
switch (activeNetwork.getType()) {
case ConnectivityManager.TYPE_WIFI:
networkType = "Wifi";
break;
case ConnectivityManager.TYPE_MOBILE:
networkType = "Mobile Data";
break;
case ConnectivityManager.TYPE_ETHERNET:
networkType = "Ethernet";
break;
case ConnectivityManager.TYPE_WIMAX:
networkType = "WiMAX";
break;
case ConnectivityManager.TYPE_VPN:
networkType = "VPN";
break;
}
this.networkType = networkType;
}
// Gets the wifi information, and updates the class variables
private void setWifiInfo() {
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] network = cm.getAllNetworks();
NetworkCapabilities netCapab = cm.getNetworkCapabilities(network[0]);
WifiManager wifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
if (wifiInfo != null) {
this.ssid = wifiInfo.getSSID();
this.ipAddress = Formatter.formatIpAddress(wifiInfo.getIpAddress());
this.macAddress = wifiInfo.getMacAddress();
this.linkSpeed = wifiInfo.getLinkSpeed();
this.frequency = wifiInfo.getFrequency();
this.dlBandwidth = netCapab.getLinkDownstreamBandwidthKbps();
this.upBandwidth = netCapab.getLinkUpstreamBandwidthKbps();
this.signalLevel = wifiManager.calculateSignalLevel(wifiManager.getConnectionInfo().getRssi(), SIGNAL_LEVEL_LIMIT);
}
}
}
当应用程序最初运行时,它运行良好,但运行的速度越来越慢,最终在10分钟左右后崩溃。我在logcat中不断收到此错误,并不断出现:我/编排者:跳过了183帧! 该应用程序可能在其主线程上做太多工作。
哦,我是这样处理的: 延迟执行任务吗? 也是这样: 每秒更新TextView
但是没有一个有效。 有人请救我...
方法getLatency(...)
是一个长期运行的操作(您启动外部进程并执行一些I / O)。 在更新UI的主线程中不应调用此类内容。 Choreographer尝试保持60fps,因此3秒钟的主线程阻塞可能导致180个丢帧。
启动一些后台任务,获取所需的所有数据,然后在主线程中更新UI。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.