在 Android 中,如何将互联网上的文本文件保存到 sdcard、从 sdcard 加载文件并用逗号将文件的条目分隔到 ListView 中?
重要的是可以一次选择 ListView 中的多个条目。片段的使用也很好,因为它可以更容易地用于不同的屏幕尺寸,例如手机和平板电脑。
在 Android 中,如何将互联网上的文本文件保存到 sdcard、从 sdcard 加载文件并用逗号将文件的条目分隔到 ListView 中?
重要的是可以一次选择 ListView 中的多个条目。片段的使用也很好,因为它可以更容易地用于不同的屏幕尺寸,例如手机和平板电脑。
我将您的问题视为 2 个不同的问题,每个问题都有自己的解决方案和障碍,最终结合在一起。我的示例都是针对 API16(4.1 Jelly Bean)编译的,至少有 API11(3.0 Honeycomb)。- 警告 -大量文本传入。
起初从互联网加载似乎势不可挡,尽管最终很简单。首先,您要确保设备具有连接。为此,您创建一个名为getConnectivityStatus
如下所示的方法:
public boolean getConnectivityStatus() {
ConnectivityManager cm = (ConnectivityManager) this
.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null)
return info.isConnected();
else
return false;
}
如果存在连接,您将需要创建一个目录来保存文件并使用 DownloadManager 类下载文件。为此,只需说:
File directory = new File(Environment.getExternalStorageDirectory(), "ExampleDirectory");
if (!directory.exists())
directory.mkdir();
接下来,您需要使用 方法下载文件downloadFile(String)
,并传入您想要的文件名。如果您在任何给定时间只想要文件的一个副本,则必须在下载前删除旧文件(如果它存在),否则您将拥有多个文件,例如 examplefile.txt;示例文件-1.txt;示例文件-2.txt;将第一部分代码放在您要开始下载的方法中,例如onClick
:
String FILE_NAME = "examplefile.txt",
File examplefile = new File(Environment.getExternalStorageDirectory()
+ "/ExampleDirectory", FILE_NAME);
if (examplefile.exists()) {
boolean deleted = examplefile.delete();
if (deleted) {
if (getConnectivityStatus())
downloadFile(FILE_NAME);
}
}
downloadFile(String)
方法:
public void downloadFile(String FILE_NAME) {
String url = "http://www.example.com/filetobedownloaded.txt";
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse(url));
request.setDescription("Example file to be displayed.");
request.setTitle(FILE_NAME);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
}
request.setDestinationInExternalPublicDir("ExampleDirectory", FILE_NAME);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
您还可以注册一个接收器以在下载完成时返回回调。为此,只需在onCreate
方法中注册接收器,如下所示:registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
并将以下方法放在您的类中:
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
if (!started) {
started = true;
// perform action upon completion
}
}
};
这是最后一DownloadFile.java
堂课:
public class DownloadFile extends Activity {
boolean started = false;
String url = "http://www.example.com/filetobedownloaded.txt";
String FILE_NAME = "examplefile.txt",
File directory = new File(Environment.getExternalStorageDirectory(), "ExampleDirectory");
File examplefile = new File(Environment.getExternalStorageDirectory()
+ "/ExampleDirectory", FILE_NAME);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_downloadfile);
registerReceiver(onComplete, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));
check();
}
public void check {
if (!directory.exists())
directory.mkdir();
if (!getConnectivityStatus()) {
if (!started) {
started = true;
// perform action if no connection
}
}
if (examplefile.exists()) {
boolean deleted = examplefile.delete();
if (deleted && !started) {
if (getConnectivityStatus())
downloadFile(FILE_NAME);
}
}
}
public boolean getConnectivityStatus() {
ConnectivityManager cm = (ConnectivityManager) this
.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info != null)
return info.isConnected();
else
return false;
}
public void downloadFile(String FILE_NAME) {
String url = "http://www.example.com/filetobedownloaded.txt";
DownloadManager.Request request = new DownloadManager.Request(
Uri.parse(url));
request.setDescription("Example file to be displayed.");
request.setTitle(FILE_NAME);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
}
request.setDestinationInExternalPublicDir("ExampleDirectory", FILE_NAME);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
}
BroadcastReceiver onComplete = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
if (!started) {
started = true;
// perform action upon completion
}
}
};
为了将文件加载到 ListFragment 中,并稍后显示所选项目,您必须在布局目录中创建 3 个类和 2 个 xml 文件。在我的示例中,我将使用MainActivity.java
、 PreviewFragment.java
、 SelectionFragment.java
、 activity_main.xml
和fragment_preview.xml
。我们将从 xml 开始。第一个 xml 文件是您正在查看的文件,其中包含我们正在使用的两个片段:ListFragment 和 PreviewFragment。设置相当简单;您指定两个片段、它们的 id 和约束以及它们各自的类。这里是activity_main.xml
:
<?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="horizontal" >
<fragment
android:id="@+id/fragmentSelection"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
class="com.smarticle.catering.update.SelectionFragment" />
<fragment
android:id="@+id/fragmentPreview"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.smarticle.catering.update.PreviewFragment" />
</LinearLayout>
上述布局针对横向模式下的平板电脑进行了优化。如果您愿意,可以调整安排。
接下来,您必须在 xml 中指定 PreviewFragment,这也相当简单,因为它只是一个水平和垂直居中的 TextView,最终将显示所选项目。这里是fragment_preview.xml
:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="@+id/tvPreview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/app_name"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
ListFragment 将在运行时创建,因此它不需要自己的 xml 文件。
为了在屏幕上显示片段,您必须activity_main.xml
在活动中加载布局。这是一项非常简单的任务,因为它看起来就像其他所有活动一样。这是MainActivity.java
:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
就是这样,认真的。但现在继续。为了更改 PreviewFragment 中的文本,您必须在 中扩展Fragment
类PreviewFragment.java
,膨胀视图并设置 setText 方法。类PreviewFragment.java
如下图所示:
public class PreviewFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_preview, container,
false);
return view;
}
public void setText(String item) {
TextView tvPreview = (TextView) getView().findViewById(R.id.tvPreview);
tvPreview.setText(item);
}
}
片段的生命周期可以在这里找到。
现在您必须设置 ListFragment。这将在ListFragment.java
课堂上完成。在该onActivityCreated()
方法中,您需要加载文件,确保它实际下载并位于该load(String)
方法的正确目录中。此时,您还将通过文件的分隔符将文件分隔为一个数组。这是load(String)
方法:
public void load(String FILE_NAME) {
String[] list;
String FILE_NAME = "examplefile.txt",
File directory = new File(Environment.getExternalStorageDirectory(), "ExampleDirectory");
File examplefile = new File(Environment.getExternalStorageDirectory()
+ "/ExampleDirectory", FILE_NAME);
if (examplefile.exists()) {
try {
File myFile = new File(directory + "/" + FILE_NAME);
FileInputStream fIn = new FileInputStream(myFile);
BufferedReader myReader = new BufferedReader(new InputStreamReader(
fIn));
String aDataRow = "";
String aBuffer = "";
while ((aDataRow = myReader.readLine()) != null) {
aBuffer += aDataRow;
aBuffer = aBuffer.trim();
list = aBuffer.split(",");
}
myReader.close();
if (!loaded)
Toast.makeText(getActivity(),
"Done reading '" + FILE_NAME + "'.", Toast.LENGTH_SHORT)
.show();
loaded = true;
if (!selections.equals("")) {
for (int i = 0; i < selections.size(); i++) {
getListView().setItemChecked(selections.get(i), true);
}
}
} catch (Exception e) {
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
}
这将返回字符串数组list
,其中 examplefile.txt 的内容用逗号分隔。只要 aBuffer.split(String delimiter) 的表达式与文本文件中的分隔符一致,您就可以将逗号替换为您想要的任何分隔符。布尔值loaded
只是为了确保每次重新创建活动时都不会出现新的 Toast,例如在方向更改时。
在load(String)
方法中,也是设置 ListFragment 的适配器和模式的好时机。您需要选择一个允许多选的 textViewResourceId,除非您想要单选。这可以通过简单地插入以下行在 while 语句之后顺利完成:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getActivity(),
android.R.layout.simple_list_item_activated_1, list);
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
如果需要单选,请更改ListView.CHOICE_MODE_MULTIPLE
为ListView.CHOICE_MODE_SINGLE
并更改android.R.layout.simple_list_item_activated_1
为android.R.layout.simple_list_item_1
。或者,如果您想要检查而不是突出显示,请更改为android.R.layout.simple_list_item_checked
.
在这个类中,您还必须初始化您的 PreviewFragment,onActivityCreated
方法如下:fragment = (PreviewFragment) getFragmentManager().findFragmentById(
R.id.fragmentPreview);
最后,您必须能够读取 ListFragment 中选择了哪些项目并将它们显示在 PreviewFragment 上。我使用getSelectedItems()
如下所示的方法执行此操作:
public void getSelectedItems() {
cntChoice = getListView().getCount();
items = "";
selections.clear();
SparseBooleanArray sparseBooleanArray = getListView()
.getCheckedItemPositions();
for (int i = 0; i < cntChoice; i++) {
if (sparseBooleanArray.get(i) == true) {
items += getListView().getItemAtPosition(i).toString()
+ ";\n";
selections.add(i);
}
}
if (fragment != null && fragment.isInLayout())
fragment.setText(items);
}
Stringitems
是 TextView 中显示的selections
内容,ArrayList<Integer>
用于在方向更改时恢复状态。android:configChanges="orientation"
通常,您会在标签下的AndroidManifest.xml
文件中指定一个<activity >
,但是当为纵向或横向使用单独的布局时会出现问题。如果您允许 Manifest 处理方向更改,则在更改方向时不会更改布局,因为不会像在正常情况下那样创建新活动。因此,您创建static ArrayList<Integer>
包含包含所选项目的位置。
最后要做的是在单击 ListItem 时读取并调用该getSelectedItems
方法,这是一项相当简单的任务。将其插入到您的课程中的任何位置:
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
getItems();
}
你完了!现在把它们放在一起。这是ListFragment.java
课程:
public class ListFragment extends ListFragment {
String FILE_NAME = "examplefile.txt", items = "";
String[] list;
static ArrayList<Integer> selections = new ArrayList<Integer>();
int cntChoice, position;
static boolean loaded = false;
File directory = new File(Environment.getExternalStorageDirectory(), "ExampleDirectory");
File examplefile = new File(Environment.getExternalStorageDirectory()
+ "/ExampleDirectory", FILE_NAME);
PreviewFragment fragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
fragment = (PreviewFragment) getFragmentManager().findFragmentById(
R.id.fragmentPreview);
check();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
getSelectedItems();
}
public void getSelectedItems() {
cntChoice = getListView().getCount();
items = "";
selections.clear();
SparseBooleanArray sparseBooleanArray = getListView()
.getCheckedItemPositions();
for (int i = 0; i < cntChoice; i++) {
if (sparseBooleanArray.get(i) == true) {
items += getListView().getItemAtPosition(i).toString()
+ ";\n";
selections.add(i);
}
}
if (fragment != null && fragment.isInLayout())
fragment.setText(items);
}
public void check() {
if (examplefile.exists())
load(FILE_NAME);
}
public void load(String FILE_NAME) {
try {
File myFile = new File(directory + "/" + FILE_NAME);
FileInputStream fIn = new FileInputStream(myFile);
BufferedReader myReader = new BufferedReader(new InputStreamReader(
fIn));
String aDataRow = "";
String aBuffer = "";
while ((aDataRow = myReader.readLine()) != null) {
aBuffer += aDataRow;
aBuffer = aBuffer.trim();
list = aBuffer.split(",");
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getActivity(),
android.R.layout.simple_list_item_activated_1, list);
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
myReader.close();
if (!loaded)
Toast.makeText(getActivity(),
"Done reading '" + FILE_NAME + "'.", Toast.LENGTH_SHORT)
.show();
loaded = true;
if (!selections.equals("")) {
for (int i = 0; i < selections.size(); i++) {
getListView().setItemChecked(selections.get(i), true);
}
getSelectedItems();
}
} catch (Exception e) {
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT)
.show();
}
}
}
我希望这能解决你的问题。我知道它很长,但它很彻底,经过测试并且效果很好。要开始这个,你可以在类的接收者Intent intent = new Intent(getBaseContext(), MainActivity.class); startActivity(intent); finish();
的方法中做一个。我还建议在方法中放置相同的代码行,特别是在没有连接时调用的部分,在这种情况下,它将加载先前下载到目录中的文件。Good luck, happy coding and always remember... 01101000011101000111010001110000011100110011101000101111001011110111011101110111011101110010111001111001011011110111010101110100011101010110001001100101001011100110001101101111011011010010111101110111011000010111010001100011011010000011111101110110001111010110100101110101011000100100101000101101010110000101001101001100001110010110011101101111onReceive
DownloadFile.java
check()