[英]How to create an activity that displays a log file and observe it to refresh its layout?
I would like to display a log file that I save in the data directory of my application ("/data/data/mypackage/files/log.txt"). 我想显示一个保存在应用程序数据目录中的日志文件(“ /data/data/mypackage/files/log.txt”)。
I need it to debug my application without eclipse . 我需要它来调试我的应用程序而无需eclipse 。
At the moment, I display the content file in a textview, and when I want to refresh the view I click on a button that reload my textview. 此刻,我在textview中显示内容文件,当我想要刷新视图时,我单击一个按钮以重新加载我的textview。 It is ugly but it works.
这很丑陋,但可以。
What I would like is an automatic refresh of my textview when my log file has been modified as in eclipse logcat. 我想要的是当我的日志文件像在eclipse logcat中一样被修改后, 自动刷新textview的功能 。
So how can I do it ? 那我该怎么办呢?
Here is what I have done : 这是我所做的:
public class LogActivity extends Activity {
private TextView textView;
private String fileName = "/data/data/my.package.app/files/log.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.log);
Typeface tf = Typeface.createFromAsset(getAssets(), "CONSOLA.TTF");
textView = (TextView) findViewById(R.id.textView1);
textView.setTypeface(tf);
setTextView();
new FileObserver(fileName) {
@Override
public void onEvent(int event, String path) {
Log.e("File", "EVENT");
if (event == FileObserver.MODIFY) {
Log.e("File", "MODIFY");
setTextView();
}
}
}.startWatching();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.log_activity, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_reload:
setTextView();
break;
case R.id.menu_empty:
File file = new File(fileName);
file.delete();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
setTextView();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
private void setTextView() {
try {
FileReader fileReader = new FileReader(new File(fileName));
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = "";
StringBuilder builder = new StringBuilder("");
while ((line = bufferedReader.readLine()) != null) {
builder.insert(0, line + "\n");
}
textView.setText(builder.toString());
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ScrollView
android:id="@+id/SCROLLER_ID"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:fillViewport="true">
<TextView
android:id="@+id/textView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</ScrollView>
</LinearLayout>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_reload"
android:title="Recharger"
android:orderInCategory="100"
android:showAsAction="always" />
<item android:id="@+id/menu_empty"
android:title="Vider"
android:orderInCategory="100"
android:showAsAction="always" />
</menu>
When I modify my log file (through an Android Service), I have sometimes the event that the file has been modified but not each time. 当我(通过Android服务)修改日志文件时,有时会发生文件已被修改但并非每次都被修改的事件。 why ?
为什么呢? (if I reload manually the view through the menu, then I see that the log file has been updated).
(如果我通过菜单手动重新加载视图,那么我看到日志文件已更新)。
The call to setTextView() inside the FileObserver is never called ? 从不调用FileObserver内部对setTextView()的调用?
Finally here is my solution (even if the Arkadiusz's one is nice). 最后,这是我的解决方案(即使Arkadiusz的解决方案不错)。
I have implemented a Service that is observing the file and I've registered it in my LogActivity : 我已经实现了一个正在观察文件的服务,并且已经在LogActivity中注册了它:
public class LogService extends Service {
public static final String BROADCAST_FILE_LOG_UPDATE = "my.package.app.log.update";
private String fileName = "/data/data/my.package.app/files/log.txt";
/**
* The intent thanks to which is forwarded the alarm to display.
*/
private Intent logIntent;
private FileObserver fileObserver;
@Override
public void onCreate() {
Log.e("LogService", "oncreate");
logIntent = new Intent(BROADCAST_FILE_LOG_UPDATE);
fileObserver = new FileObserver(fileName) {
@Override
public void onEvent(int event, String path) {
if (event == FileObserver.MODIFY) {
broadcastLogUpdate();
}
}
};
}
private void broadcastLogUpdate() {
sendBroadcast(logIntent);
}
@Override
public void onStart(Intent intent, int startid) {
fileObserver.startWatching();
}
@Override
public void onDestroy() {
fileObserver.stopWatching();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class LogActivity extends Activity {
private TextView textView;
private String fileName = "/data/data/my.package.app/files/log.txt";
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
setTextView();
}
};
private Intent serviceIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
serviceIntent = new Intent(getApplicationContext(), LogService.class);
setContentView(R.layout.log);
Typeface tf = Typeface.createFromAsset(getAssets(), "CONSOLA.TTF");
textView = (TextView) findViewById(R.id.textView1);
textView.setTypeface(tf);
setTextView();
}
@Override
protected void onResume() {
super.onResume();
try {
startService(serviceIntent);
registerReceiver(broadcastReceiver, new IntentFilter(LogService.BROADCAST_FILE_LOG_UPDATE));
} catch (IllegalArgumentException e) {}
}
@Override
protected void onStop() {
super.onStop();
try {
unregisterReceiver(broadcastReceiver);
} catch (IllegalArgumentException e) {}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.log_activity, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_reload:
Toast.makeText(getApplicationContext(), "reload", Toast.LENGTH_LONG).show();
setTextView();
break;
case R.id.menu_empty:
new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Erase log file ?").setMessage("Sure ?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
File file = new File(fileName);
file.delete();
try {
file.createNewFile();
unregisterReceiver(broadcastReceiver);
stopService(serviceIntent);
startService(serviceIntent);
registerReceiver(broadcastReceiver, new IntentFilter(
LogService.BROADCAST_FILE_LOG_UPDATE));
} catch (IOException e) {
e.printStackTrace();
}
setTextView();
}
}).setNegativeButton("No", null).show();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
private void setTextView() {
try {
FileReader fileReader = new FileReader(new File(fileName));
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line = "";
StringBuilder builder = new StringBuilder("");
while ((line = bufferedReader.readLine()) != null) {
builder.insert(0, line + "\n");
}
textView.setText(builder.toString());
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Of course, don't forget to add the new service in the manifest. 当然,不要忘记在清单中添加新服务。
<service android:name=".LogService" />
It works very well. 效果很好。
I hope it would be useful for somebody else. 我希望这对其他人有用。
I have been strugling with the same task lately (not logtcat though) and I ended up using this library: http://www.informit.com/guides/content.aspx?g=java&seqNum=226 我最近一直在努力完成同一任务(虽然不是logtcat),但最终还是使用了这个库: http : //www.informit.com/guides/content.aspx? g=java&seqNum=226
It uses RandomFileAccess class to get changes - by comparing current & last filepointer positions. 它使用RandomFileAccess类获取更改-通过比较当前和最后一个文件指针位置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.