0

我想显示一个保存在应用程序数据目录中的日志文件(“/data/data/mypackage/files/log.txt”)。

我需要它在没有 eclipse的情况下调试我的应用程序。

目前,我在 textview 中显示内容文件,当我想刷新视图时,我单击一个重新加载我的 textview 的按钮。它很丑,但它有效。

我想要的是当我的日志文件被修改为 eclipse logcat 时自动刷新我的文本视图。

那么我该怎么做呢?

这是我所做的:


我的活动:


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>
  • 当我修改我的日志文件(通过 Android 服务)时,我有时会遇到文件已被修改但不是每次都被修改的事件。为什么 ?(如果我通过菜单手动重新加载视图,那么我会看到日志文件已更新)。

  • FileObserver 中对 setTextView() 的调用永远不会被调用?

4

2 回答 2

1

最后这是我的解决方案(即使 Arkadiusz 的解决方案很好)。

我已经实现了一个正在观察文件的服务,并且我已经在我的 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();
    }
}

}

当然,不要忘记在清单中添加新服务。


清单:


    <service android:name=".LogService" />

它工作得很好。

我希望它对其他人有用。

于 2013-07-30T12:50:41.403 回答
0

我最近一直在为同样的任务苦苦挣扎(虽然不是 logtcat),我最终使用了这个库:http ://www.informit.com/guides/content.aspx?g=java&seqNum=226

它使用 RandomFileAccess 类来获取更改 - 通过比较当前和最后一个文件指针位置。

于 2013-07-30T10:04:30.650 回答