Inflesを使用してアセットからSDカードにファイルを置く

こんにちは、ハブラフチアン!



説明:



ほとんどすべてのAndroidユーザーは、SDカードのファイルを使用したアプリケーションの実践を知っています。

ほとんどのアプリケーションはこれらのファイルをインターネットからダウンロードしてフォルダーに入れますが、すべてのユーザーがネットワークからダウンロードできるわけではなく、すべての開発者が独自のサーバーを持っているわけではなく、手動でファイルをコピーするのは不便です。

したがって、すべての人の生活を簡素化するために、Inflesプログラムが作成され、オープンソースコードおよびMITライセンスの下で無料で配布されています。 プログラムを使用すると、設定で指定されたSDカードのフォルダーに1クリックで必要なファイルをインストールできます。 これを行うには、アセットフォルダーに配置し、変数「COPY_DIR」のファイル「\ Infles \ src \ ru \ boomik \ infles \ InflesActivity.java」のコードでメモリカード上のパスを指定し、プログラムをコンパイルします。



プログラムのアイデアは、特定のフォルダー内のフラッシュドライブにファイルをコピーする必要があったすべての機能にアクセスするために、アプリケーションを使用したときに現れましたが、組み込みのメカニズムはありませんでした。









そして今、作成とコードについて。



アプリケーションはシンプルであることが判明し、これがその目的であるシンプルさと使いやすさです。 アクティビティとサービスの2つのクラスのみで構成されています(安定性を高めるため)。 このサービスには意味のあるものは何もありませんが、アクティビティを分析してみましょう。すべての機能が含まれています(記事の最後で、ソースコードとサンプルアプリケーションへのリンクを提供します)。

アプリケーションのレイアウト(レイヤー)には、4つのボタンがあります-1つは大きく、ほぼ画面全体と3つ(SHOW_BUTTONの値をfalseに変更することで非表示にできます)。

アクティビティには、以下で説明する多くの機能が含まれています。

コードは複雑ではありませんが、すべてをポイントごとに説明します。 コード自体はクラス内にあるため、順番に進みます。



package ru.boomik.infles; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Intent; import android.content.res.AssetManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.text.Html; import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; public class InflesActivity extends Activity { private static final String LOG_TAG = "Infles:InflesActivity"; private static final int ABOUT = 1; private static final int PROGRESS = 2; boolean resCopy; String[] wrong = { "images", "sounds", "webkit" }; // boolean SHOW_BUTTON = true; boolean UNZIP = false; boolean DEL_ZIP = false; String COPY_DIR = "Infles"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //  Button ActButton = (Button)findViewById(R.id.ActButton); ImageButton Exit = (ImageButton)findViewById(R.id.exit); ImageButton About = (ImageButton)findViewById(R.id.about); ImageButton Delete = (ImageButton)findViewById(R.id.delete); // Listener' ActButton.setOnClickListener(ActListener); Exit.setOnClickListener(ExitListener); About.setOnClickListener(AboutListener); Delete.setOnClickListener(DeleteListener); // ,  SHOW_BUTTON = false if (!SHOW_BUTTON) { Exit.setVisibility(View.GONE); About.setVisibility(View.GONE); Delete.setVisibility(View.GONE); } }
      
      





必要なインポートを実行し、InflesActivityクラスとプログラムが動作するために必要な変数を宣言し、それらの下で設定を行います。



boolean SHOW_BUTTON = true; -画面に追加のボタンを表示します。

ブールUNZIP = false; -zipアーカイブを解凍します。

boolean DEL_ZIP = false; -zipアーカイブを削除します(unpackオプションが有効な場合のみ)。

文字列COPY_DIR = "Infles"; -SDカード上のパス。 先頭または末尾に「/」を入れないでください。



onCreate関数では、すべてのボタンが最初に定義され(ActButton、Delete、About、Exit)、次にListenerボタンに割り当てられ、SHOW_BUTTON変数がチェックされ、falseの場合、ボタンは非表示になります。



  private OnClickListener ActListener = new OnClickListener() { public void onClick(View v) { showDialog(PROGRESS); //  - startService(new Intent(InflesActivity.this,InflesService.class)); final String dir="/"+COPY_DIR+"/"; final String sdDir="/sdcard" +dir; final AssetManager am = getAssets(); //   Assets //  new Thread(new Runnable() { public void run() { try { String[] files = am.list(""); for(int i=0; i<files.length; i++) { if (!CheckMass(files[i],wrong)) { dirChecker(dir); // checking directory copy(files[i],dir); if (UNZIP) { String filename = files[i]; int dotPos = filename.lastIndexOf("."); String ext = filename.substring(dotPos); //   if (ext.equals(".zip")) { File File = new File(Environment.getExternalStorageDirectory()+ dir + filename); if (File.exists()) { unzip(File,sdDir,dir); if (DEL_ZIP) { File.delete(); } } else Log.i(LOG_TAG, dir + filename+" not exists"); } } } } } catch (IOException e1) { e1.printStackTrace(); } InflesActivity.this.runOnUiThread(new Runnable() { public void run() { dismissDialog(PROGRESS); // - } }); } }).start(); exit(); DeleteApp(); } };
      
      







「RUN!」ボタンを押すためのハンドラー。 最初に、進行状況ダイアログが呼び出され(コードがオンになっています)、プログラムで使用するために新しい変数が宣言されます。 その後、新しいストリームで、「Assets」フォルダーからすべてのファイルが読み込まれ、「AssetManager」タイプの変数「am」が宣言されます。 次に、「CheckMass()」関数を使用して、ファイルが名前のブラックリストにあるかどうかを確認します(何らかの理由で、Assetsフォルダーを読み取るときに、残ったフォルダーがあり、まだ理由を把握していないが、それらをふるいにかけます)。「dirChecker()」関数は、存在しない場合は作成され、「copy()」関数によるファイルの実際のコピーが行われます。 コードの次のセクションでは、アーカイブを抽出するオプションが有効になっているかどうかを確認し、有効になっている場合はファイルの拡張子を確認し、見つかった場合は現在のフォルダーから解凍します(関数「Unzip()」)。 アーカイブにはサブフォルダーが含まれている可能性があります。これは例に示されていますが、Assetsフォルダーにサブフォルダーのみがある場合、コピーされません。解決策を探します。 次に、ダイアログ、スレッド、およびプログラムが閉じられ、プログラム削除ダイアログが呼び出されます。その機能は完了しており、保存する意味がありませんが、キャンセルをクリックすると、そのまま残ります。



  //   private OnClickListener ExitListener = new OnClickListener() { public void onClick(View v) { exit(); } }; private OnClickListener AboutListener = new OnClickListener() { public void onClick(View v) { showDialog(ABOUT); } }; private OnClickListener DeleteListener = new OnClickListener() { public void onClick(View v) { exit(); DeleteApp(); } }; private void exit() { finish(); stopService(new Intent(InflesActivity.this,InflesService.class)); } private void DeleteApp() { Uri packageURI = Uri.parse("package:ru.boomik.infles"); Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI); startActivity(uninstallIntent); }
      
      







ここでは、残りの3つの追加ボタンのリスナーが実行され、それらの関数が呼び出されます。 showDialog(ABOUT)関数はAboutダイアログを呼び出し、Exit()関数はアクティビティを閉じてサービスを停止し、DeleteApp()関数はアプリケーションのアンインストールダイアログを開きます。



  protected Dialog onCreateDialog(int id) { //  super.onCreateDialog(id); switch(id) { case ABOUT: // " " //Context mContext = getApplicationContext(); Dialog dialog = new Dialog(this); dialog.setContentView(R.layout.about); dialog.setTitle("About"); TextView text = (TextView) dialog.findViewById(R.id.text); text.setText(Html.fromHtml("Infles - programm from copy files from app to SD card.<br /><br />Author: Kirill \"BOOM\" Ashikhmin<br />Email: <a href=\"mailto:boom.vrn@gmail.com\">boom.vrn@gmail.com</a><br />Site: <a href=\"http://boomik.ru\">http://boomik.ru</a><br />Source: <a href=\"http://code.google.com/p/infles/\">http://code.google.com/p/infles/</a><br /><br />License: MIT.")); text.setMovementMethod(LinkMovementMethod.getInstance()); ImageView image = (ImageView) dialog.findViewById(R.id.image); image.setImageResource(R.drawable.icon); return dialog; case PROGRESS: //   ProgressDialog dialogPr = new ProgressDialog(this); dialogPr.setTitle("Please, wait..."); dialogPr.setMessage("Copying files..."); dialogPr.setIndeterminate(true); return dialogPr; default: dialog = null; } return null; }
      
      





この関数は、「プログラムについて」ダイアログと進行状況ダイアログが開かれたときに呼び出されます。 「int」型の変数が関数に渡され、それに基づいて、対応するダイアログが呼び出されます。 ダイアログ自体について説明します-インターネット上にはすでに多くの記事があり、developer.android.comに良い例があります。 「プログラムについて」ウィンドウは独自のxmlレイアウトを使用しており、テキストはコードから表示され、リンクをサポートするhtmlコードの形式で表示されているとしか言えません。







  private boolean copy(String fileName, String dir) { try { AssetManager am = getAssets(); File destinationFile = new File(Environment.getExternalStorageDirectory()+ dir + fileName); // InputStream in = am.open(fileName); //   FileOutputStream f = new FileOutputStream(destinationFile); byte[] buffer = new byte[1024]; int len1 = 0; while ((len1 = in.read(buffer)) > 0) { f.write(buffer, 0, len1); } f.close(); resCopy=true; } catch (Exception e) { Log.d(LOG_TAG, e.getMessage()); resCopy=false; } return resCopy; }
      
      





これはプログラムコピーファイルの主な機能であり、極端に複雑なものはありません。ファイルへのリンクがdestinationFile変数に表示され、ファイルが開いて1 kb単位でコピーされます。

  public void unzip(File zip,String location,String dir) //   { Log.i(LOG_TAG,zip +" unzipped"); try { FileInputStream fin = new FileInputStream(zip); ZipInputStream zin = new ZipInputStream(fin); ZipEntry ze = null; while ((ze = zin.getNextEntry()) != null) { if(ze.isDirectory()) { dirChecker(dir+ze.getName()); } else { FileOutputStream fout = new FileOutputStream(location + ze.getName()); for (int c = zin.read(); c != -1; c = zin.read()) { fout.write(c); } zin.closeEntry(); fout.close(); } } zin.close(); } catch(Exception e) { } }
      
      





zipアーカイブを抽出する機能。 アーカイブの操作に標準のJava言語関数を使用します。

  private void dirChecker(String dir) { File Directory = new File("/sdcard"+dir); Log.i(LOG_TAG,"/sdcard"+dir +" - dir check"); if(!Directory.isDirectory()) { Directory.mkdirs(); } } static public boolean CheckMass(String text, String[] arr) { boolean res=false; int strLenght=arr.length; for (int i=0;i<strLenght;i++){ if (text.equals(arr[i])){ res=true; break; }} return res; }
      
      





フォルダーが存在しない場合、フォルダーの作成を確認し、ファイルのブラックリストの配列で変数値を検索するための2つの小さな関数。

  @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu, menu); //   menu.xml return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.delete: exit(); DeleteApp(); return true; case R.id.about: showDialog(ABOUT); return true; case R.id.exit: exit(); return true; } return super.onOptionsItemSelected(item); } }
      
      







さて、ここにメニューが表示されます。これは、ご想像のとおり、Androidデバイスの「メニュー」ハードキーによって呼び出されます。



レイアウトファイルとメニューは最も単純なので、記事では説明しません。気にする人は、SVNにコードを表示して例を調べてもらいます。



あなたがプログラムに対する希望、またはコードを改善する方法についての提案がある場合-書く、私はそれを実装しようとします。

このプログラムは完全に無料であり、制限なくプロジェクトで使用できますが、元の名前と「プログラムについて」ウィンドウを残すことをお勧めします。



難しさ



最初の難しさはパスアドレスに関連しており、異なる場所では、それらを異なる方法で記述する必要がありました。

2番目は、サブフォルダーを作成できないことでした。アーカイブからの抽出を導入することにしました。

3番目は、ファイルまたはフォルダーのロシア語の名前を設定する機能ではありません。 まだ決めていませんが、それだけの価値はありますか?

4番目の問題は、その原因と方法がわからない-フィルターが適用されるAssetsフォルダーに拡張子のない隠しファイル。



参照資料



SVNプロジェクトコード: code.google.com/p/infles

プログラムの例: infles.googlecode.com/files/Infles.apk

(ファイル「Infles.txt」をフォルダー「Infles」にコピーし、ファイル「Infles from zip.txt」とフォルダー「Subfolder from zip」を含むアーカイブを抽出します。フォルダーには「Infles from subfolder zip.txt」が含まれます)



PS MITのライセンスを変更し、リポジトリのソースコードを削除しました。



All Articles