package com.javacourse.rongsonho.androidsocketclient;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Socket socket;
//從手機裡的”我的檔案”選張照片,準備傳到電腦,
//因不同的手機路徑可能不同,可自行修改。
//public static final String file_name = “//storage/MicroSD/DCIM/Hello.jpg”;
Button imageChooser, connecter, refreshLog;
OutputStream outputstream;
String ImagePath=””, timeString=””;
BufferedInputStream bis;
FileInputStream fis;
TextView statusText;
static byte[] mybytearray;
int serverPort;
InetAddress serverAddr;
MyDBHandler dbHandler;
SimpleDateFormat formatter;
Date curDate;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageChooser = (Button)findViewById(R.id.button);
connecter = (Button) findViewById(R.id.button2);
refreshLog = (Button) findViewById(R.id.refreshLog);
statusText = (TextView) findViewById(R.id.textView);
statusText.setMovementMethod(ScrollingMovementMethod.getInstance());
formatter = new SimpleDateFormat(“yyyy年MM月dd日HH:mm:ss”);
Date curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
String timeString = formatter.format(curDate);
dbHandler = new MyDBHandler(this, null, null, 1);
dbHandler.addLog(“[*]”+ timeString +”: Choose a picture to send to PCn”);
printDatabase();
imageChooser.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
// 建立 “選擇檔案 Action” 的 Intent
Intent intent = new Intent(Intent.ACTION_PICK);
// 過濾檔案格式
intent.setType(“image/*”);
// 建立 “檔案選擇器” 的 Intent (第二個參數: 選擇器的標題)
Intent destIntent = Intent.createChooser(intent, “選擇檔案”);
// 切換到檔案選擇器 (它的處理結果, 會觸發 onActivityResult 事件)
startActivityForResult(destIntent, 0);
}
});
connecter.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread test = new Thread(clientSocket);
test.start();
//statusText.setText(statusText.getText() + “[*] Connecting to server: ” + serverAddr.toString() + “/” + serverPort + ” …n”);
//statusText.setText(statusText.getText()+”[*] Done!”);
}
});
refreshLog.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
printDatabase();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
// 有選擇檔案
if ( resultCode == RESULT_OK ) {
// 取得檔案的 Uri
if (data != null) {
Log.e(“Socket”, “great, data is not null”);
Uri uri = data.getData();
if (uri != null) {
String path = MagicFileChooser.getAbsolutePathFromUri(this,uri);
ImagePath = “/”+ path;
Log.e(“Socket”, ImagePath);
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
dbHandler.addLog(“[*]”+timeString+”: “+ “ImagePath: “+ ImagePath + ” n”);
File myFile = new File(ImagePath);
if (myFile.exists()) {
try {
mybytearray = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis, 8 * 1024);
bis.read(mybytearray, 0, mybytearray.length);
Log.e(“Socket”, mybytearray.toString());
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
Log.e(“Socket”, “File read done!”);
dbHandler.addLog(“[*]”+timeString + “: Image has been chosenn”);
printDatabase();
} catch (IOException e) {
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
Log.e(“Socket”, “File read error!”);
dbHandler.addLog(“[*]”+timeString + “: file read error!”);
printDatabase();
}
//輸出到電腦
} else {
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
Log.e(“Socket”, “file doesn’t exist!”);
dbHandler.addLog(“[*]”+timeString + “: file doesn’t exist!”);
printDatabase();
}
} else {
setTitle(“無效的檔案路徑 !!”);
}
} else {
setTitle(“取消選擇檔案 !!”);
}
}
}
Runnable clientSocket = new Runnable() {
@Override
public void run() {
try {
serverAddr = InetAddress.getByName(“172.20.10.4”);
serverPort = 5987;
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
Log.e(“Socket”, “Client: Connecting…”);
dbHandler.addLog(“[*]”+ timeString + “: Client: Connecting…: ” + serverAddr + “/” + serverPort + “n”);
//printDatabase();
try {
socket = new Socket(serverAddr, serverPort);
outputstream = socket.getOutputStream();
outputstream.write(mybytearray, 0, mybytearray.length);
outputstream.flush();
} catch (Exception e) {
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
Log.e(“Socket”, “Client: Error”, e);
dbHandler.addLog(“[*]”+timeString+ “: Client: Error” + e + “n”);
//printDatabase();
} finally {
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
Log.e(“Socket”, “Transfer done!”);
dbHandler.addLog(“[*]”+timeString+ “: Transfer done!n”);
socket.close();
}
} catch (Exception e) {
curDate = new Date(System.currentTimeMillis()) ; // 獲取當前時間
timeString = formatter.format(curDate);
Log.e(“Socket”, “Client: Error”, e);
dbHandler.addLog(“[*]”+timeString+ “: Client: Error” + e + “n”);
//printDatabase();
}
}
};
public void printDatabase(){
String DBString = dbHandler.databaseToString();
statusText.setText(DBString);
}
}
3. MyDBHandler.java:
package com.javacourse.rongsonho.androidsocketclient;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by RongSonHo on 5/24/16.
*/
public class MyDBHandler extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = “socket.db”;
private static final String TABLE_LOG = “socket_log”;
private static final String COLUME_ID = “_id”;
private static final String COLUME_LOG= “socketLog”;
public MyDBHandler(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, factory, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
String query = “CREATE TABLE ” + TABLE_LOG + ” ( ” +
COLUME_ID + ” INTEGER PRIMARY KEY AUTOINCREMENT, ” +
COLUME_LOG + ” TEXT ” +
“);”;
db.execSQL(query);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(“DROP TABLE IF EXISTS ” + TABLE_LOG);
onCreate(db);
}
public String databaseToString(){
String dbString = “”;
SQLiteDatabase db = getWritableDatabase();
String query = “SELECT * FROM ” + TABLE_LOG + ” WHERE 1″;
Cursor cursor = db.rawQuery(query, null);
cursor.moveToFirst();
while(!cursor.isAfterLast()){
if(cursor.getString(cursor.getColumnIndex(COLUME_LOG))!= null){
dbString += cursor.getString(cursor.getColumnIndex(COLUME_LOG));
dbString += “n”;
}
cursor.moveToNext();
}
db.close();
return dbString;
}
public void addLog(String newlog){
ContentValues values = new ContentValues();
values.put(COLUME_LOG, newlog);
SQLiteDatabase db = getWritableDatabase();
db.insert(TABLE_LOG, null, values);
db.close();
}
public void deleteLog(){
SQLiteDatabase db = getWritableDatabase();
db.execSQL(“TRUNCATE TABLE ” + TABLE_LOG +”;” );
db.close();
}
}
4. MagicFileChooser.java: (別人寫好的工具,取自:https://magiclen.org/android-filechooser/)
package com.javacourse.rongsonho.androidsocketclient;
/**
* Created by RongSonHo on 6/20/16.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
@SuppressLint(“NewApi”)
public class MagicFileChooser {
public static final int ACTIVITY_FILE_CHOOSER = 9973;
private final Activity activity;
private boolean choosing = false;
private boolean mustCanRead;
private File[] chosenFiles;
public MagicFileChooser(final Activity activity) {
this.activity = activity;
}
public boolean showFileChooser() {
return showFileChooser(“*/*”);
}
public boolean showFileChooser(final String mimeType) {
return showFileChooser(mimeType, null);
}
public boolean showFileChooser(final String mimeType, final String chooserTitle) {
return showFileChooser(mimeType, chooserTitle, false);
}
public boolean showFileChooser(final String mimeType, final String chooserTitle, final boolean allowMultiple) {
return showFileChooser(mimeType, chooserTitle, allowMultiple, false);
}
public boolean showFileChooser(final String mimeType, final String chooserTitle, final boolean allowMultiple, final boolean mustCanRead) {
if (mimeType == null || choosing) {
return false;
}
choosing = true;
// 檢查是否有可用的Activity
final PackageManager packageManager = activity.getPackageManager();
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(mimeType);
List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (list.size() > 0) {
this.mustCanRead = mustCanRead;
// 如果有可用的Activity
Intent picker = new Intent(Intent.ACTION_GET_CONTENT);
picker.setType(mimeType);
picker.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, allowMultiple);
picker.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
// 使用Intent Chooser
Intent destIntent = Intent.createChooser(picker, chooserTitle);
activity.startActivityForResult(destIntent, ACTIVITY_FILE_CHOOSER);
return true;
} else {
return false;
}
}
public boolean onActivityResult(final int requestCode, final int resultCode, final Intent data) {
if (requestCode == ACTIVITY_FILE_CHOOSER) {
choosing = false;
if (resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
if (uri != null) {
// 單選
chosenFiles = getFilesFromUris(activity, new Uri[]{uri}, mustCanRead);
return true;
} else if (Build.VERSION.SDK_INT >= 16) {
// 複選
ClipData clipData = data.getClipData();
if (clipData != null) {
int count = clipData.getItemCount();
if (count > 0) {
Uri[] uris = new Uri[count];
for (int i = 0; i < count; i++) {
uris[i] = clipData.getItemAt(i).getUri();
}
chosenFiles = getFilesFromUris(activity, uris, mustCanRead);
return true;
}
}
}
}
}
return false;
}
public File[] getChosenFiles() {
return chosenFiles;
}
public static String[] getAbsolutePathsFromUris(final Context context, final Uri[] uris) {
return getAbsolutePathsFromUris(context, uris, false);
}
public static String[] getAbsolutePathsFromUris(final Context context, final Uri[] uris, final boolean mustCanRead) {
File[] files = getFilesFromUris(context, uris, mustCanRead);
int filesLength = files.length;
String[] paths = new String[filesLength];
for (int i = 0; i < filesLength; i++) {
paths[i] = files[i].getAbsolutePath();
}
return paths;
}
public static File[] getFilesFromUris(final Context context, final Uri[] uris) {
return getFilesFromUris(context, uris, false);
}
public static File[] getFilesFromUris(final Context context, final Uri[] uris, final boolean mustCanRead) {
ArrayList<File> fileList = new ArrayList<File>();
int urisLength = uris.length;
for (int i = 0; i < urisLength; i++) {
Uri uri = uris[i];
File file = getFileFromUri(context, uri, mustCanRead);
if (file != null) {
fileList.add(file);
}
}
File[] files = new File[fileList.size()];
fileList.toArray(files);
return files;
}
public static String getAbsolutePathFromUri(final Context context, final Uri uri) {
return getAbsolutePathFromUri(context, uri, false);
}
public static String getAbsolutePathFromUri(final Context context, final Uri uri, final boolean mustCanRead) {
File file = getFileFromUri(context, uri, mustCanRead);
if (file != null) {
return file.getAbsolutePath();
} else {
return null;
}
}
public static File getFileFromUri(final Context context, final Uri uri) {
return getFileFromUri(context, uri, false);
}
@SuppressLint(“NewApi”)
public static File getFileFromUri(final Context context, final Uri uri, final boolean mustCanRead) {
if (uri == null) {
return null;
}
// 判斷是否為Android 4.4之後的版本
final boolean after44 = Build.VERSION.SDK_INT >= 19;
if (after44 && DocumentsContract.isDocumentUri(context, uri)) {
// 如果是Android 4.4之後的版本,而且屬於文件URI
final String authority = uri.getAuthority();
// 判斷Authority是否為本地端檔案所使用的
if (“com.android.externalstorage.documents”.equals(authority)) {
// 外部儲存空間
final String docId = DocumentsContract.getDocumentId(uri);
final String[] divide = docId.split(“:”);
final String type = divide[0];
if (“primary”.equals(type)) {
String path = Environment.getExternalStorageDirectory() + “/” + divide[1];
return createFileObjFromPath(path, mustCanRead);
}
} else if (“com.android.providers.downloads.documents”.equals(authority)) {
// 下載目錄
final String docId = DocumentsContract.getDocumentId(uri);
final Uri downloadUri = ContentUris.withAppendedId(Uri.parse(“content://downloads/public_downloads”), Long.parseLong(docId));
String path = queryAbsolutePath(context, downloadUri);
return createFileObjFromPath(path, mustCanRead);
} else if (“com.android.providers.media.documents”.equals(authority)) {
// 圖片、影音檔案
final String docId = DocumentsContract.getDocumentId(uri);
final String[] divide = docId.split(“:”);
final String type = divide[0];
Uri mediaUri = null;
if (“image”.equals(type)) {
mediaUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if (“video”.equals(type)) {
mediaUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if (“audio”.equals(type)) {
mediaUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
} else {
return null;
}
mediaUri = ContentUris.withAppendedId(mediaUri, Long.parseLong(divide[1]));
String path = queryAbsolutePath(context, mediaUri);
return createFileObjFromPath(path, mustCanRead);
}
} else {
// 如果是一般的URI
final String scheme = uri.getScheme();
String path = null;
if (“content”.equals(scheme)) {
// 內容URI
path = queryAbsolutePath(context, uri);
} else if (“file”.equals(scheme)) {
// 檔案URI
path = uri.getPath();
}
return createFileObjFromPath(path, mustCanRead);
}
return null;
}
public static File createFileObjFromPath(final String path) {
return createFileObjFromPath(path, false);
}
public static File createFileObjFromPath(final String path, final boolean mustCanRead) {
if (path != null) {
try {
File file = new File(path);
if (mustCanRead) {
file.setReadable(true);
if (!file.canRead()) {
return null;
}
}
return file.getAbsoluteFile();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return null;
}
public static String queryAbsolutePath(final Context context, final Uri uri) {
final String[] projection = {MediaStore.MediaColumns.DATA};
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, projection, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
return cursor.getString(index);
}
} catch (Exception ex) {
ex.printStackTrace();
if (cursor != null) {
cursor.close();
}
}
return null;
}
}
參考文章:
1. Android 如何選取圖片或是檔案?:https://magiclen.org/android-filechooser/
2. 西加加 Android 手機資料傳到電腦: http://pianovv510.blogspot.tw/2013/04/android-wifi.html
3. Android TextView多行本文滾動輕鬆實現:http://sunylin.pixnet.net/blog/post/91068996-android-textview多行本文滾動輕鬆實現