Androidでは、インターネットからsdcardにテキストファイルを保存し、sdcardからファイルをロードし、ファイルのエントリをコンマでリストビューに区切るにはどうすればよいでしょうか。
ListViewの複数のエントリを一度に選択できることが重要です。フラグメントを使用すると、電話とタブレットなどのさまざまな画面サイズでの使用が容易になるため、フラグメントを使用することもできます。
Androidでは、インターネットからsdcardにテキストファイルを保存し、sdcardからファイルをロードし、ファイルのエントリをコンマでリストビューに区切るにはどうすればよいでしょうか。
ListViewの複数のエントリを一度に選択できることが重要です。フラグメントを使用すると、電話とタブレットなどのさまざまな画面サイズでの使用が容易になるため、フラグメントを使用することもできます。
私はあなたの質問を2つの異なる問題として見ています。それぞれに独自の解決策と障害があり、最終的には一緒になります。私の例はすべて、API11(3.0 Honeycomb)以上のAPI16(4.1 Jelly Bean)に対してコンパイルされています。-警告-大量のテキストが着信します。
インターネットからの読み込みは、最終的には簡単ですが、最初は圧倒されるようです。まず、デバイスが接続されていることを確認します。これを行うには、次のように呼ば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)
ファイル名を渡して、メソッドを使用してファイルをダウンロードします。いつでもファイルのコピーを1つだけにしたい場合は、ダウンロードする前に古いファイルが存在する場合は削除する必要があります。そうしないと、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
し ます。xmlから始めましょう。最初のxmlファイルは表示しているファイルであり、これには、作業中の2つのフラグメントであるListFragmentとPreviewFragmentが含まれています。セットアップはかなり簡単です。2つのフラグメント、それらのIDと制約、およびそれぞれのクラスを指定します。ここにあります:PreviewFragment.java
SelectionFragment.java
activity_main.xml
fragment_preview.xml
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の内容がコンマで区切られたString配列が返されます。aBuffer.split(String delimiter)の式がテキストファイルの区切り文字と一致している限り、コンマを任意の区切り文字に置き換えることができます。ブール値loaded
は、方向の変更など、アクティビティが再作成されるたびに新しいトーストが表示されないようにするためだけのものです。
この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 >
が、縦向きまたは横向きに別々のレイアウトを使用すると問題が発生します。マニフェストに向きの変更の処理を許可すると、通常の状況のように新しいアクティビティが作成されないため、向きが変更されてもレイアウトは変更されません。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()