在Android中,如何将文本文件从Internet保存到SD卡,从SD卡加载文件并用逗号分隔文件的条目到ListView?
重要的是,可以一次选择ListView中的多个条目。 片段的使用也会很好,因为它可以更容易地使用不同的屏幕尺寸,如手机和平板电脑。
答案 0 :(得分: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; examplefile-1.TXT; examplefile-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);
}
}
可以找到片段的生命周期here
现在,您必须设置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();
}
}
}
这将返回String数组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);
}
字符串items
是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();
类的接收器的onReceive
方法中执行DownloadFile.java
。我还建议在check()
方法中放置相同的代码行,特别是在没有连接的情况下调用的部分,在这种情况下,它将加载先前下载到目录的文件。祝你好运,快乐编码和永远记住... 01101000011101000111010001110000011100110011101000101111001011110111011101110111011101110010111001111001011011110111010101110100011101010110001001100101001011100110001101101111011011010010111101110111011000010111010001100011011010000011111101110110001111010110100101110101011000100100101000101101010110000101001101001100001110010110011101101111