Please copy the "libopencv_java3.so" from OpenCV sdk folder to app's jniLibs folder
The file location here:
...\OpenCV\sdk\native\libs\**Each platforms**\libopencv_java3.so
2015年11月17日 星期二
2015年10月11日 星期日
[Android] Memo - RecyclerView使用事項
RecyclerView是被放在android.support.v7.widget裡,使用前需要開啟該app的gradle檔加入
compile 'com.android.support:recyclerview-v7:23.0.1'
compile 'com.android.support:cardview-v7:23.0.1'
compile 'com.android.support:recyclerview-v7:23.0.1'
compile 'com.android.support:cardview-v7:23.0.1'
2015年7月29日 星期三
[Android] 其他class使用MainActivity元件
MainActivity.java
static MainActivity ths;
@Overrideprotected void onCreate(Bundle savedInstanceState) {....ths = this;TextView showName = (TextView)findViewById(R.id.showName);
public static MainActivity getInstance() { return ths; }....public void updateTheTextView(final String t) {MainActivity.this.runOnUiThread(new Runnable() { public void run() { showName.append(t); } }); }}Others.java
欲使用MainActivity的texview就只要如下:
MainActivity.getInstance().updateTheTextView(strAddress);
[Android] Handler should be set to static to avoid memory leak
腦弱, 每次都忘記怎麼寫, 還要去開以前的code找出來, 紀錄在這比較快 XD
private final MyHandler myhandler = new MyHandler(this);
.....
public static class MyHandler extends Handler { private final WeakReference<MainActivity> mActivity; public MyHandler(MainActivity activity) { mActivity = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { final MainActivity activity = mActivity.get(); if (activity != null) { // TODO: implement your code here } } }
2015年4月29日 星期三
[Android] Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
今天看書練習Broadcast receiver時, 在自定義的BroadcastReceiver的類別onReceive()中, 我使用了一個intent想要將廣播收到的值抓出來再丟去瀏覽器查詢, 如下
@Override
public void onReceive(Context context, Intent intent) {
String strQuery= intent.getStringExtra("QUERY_PARM");
Uri uri = Uri.parse("https://www.google.com.tw/webhp?hl=zh-TW&gws_rd=ssl#hl=zh-TW&q=" + strQuery);
Intent it = new Intent(Intent.ACTION_VIEW, uri);
context.startActivity(it);
}
但收到廣播後要開啟瀏覽器前, 程式就掛掉惹, 且DDMS出現了以下訊息:
Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
請問Google大神後, 發現如果是用context執行starActivity, 就需要再開一個新的task
解決方法就是在startActivity之前指派一個flag給intent 就OK了
Intent it = new Intent(Intent.ACTION_VIEW, uri);
it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(it);
@Override
public void onReceive(Context context, Intent intent) {
String strQuery= intent.getStringExtra("QUERY_PARM");
Uri uri = Uri.parse("https://www.google.com.tw/webhp?hl=zh-TW&gws_rd=ssl#hl=zh-TW&q=" + strQuery);
Intent it = new Intent(Intent.ACTION_VIEW, uri);
context.startActivity(it);
}
但收到廣播後要開啟瀏覽器前, 程式就掛掉惹, 且DDMS出現了以下訊息:
Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
請問Google大神後, 發現如果是用context執行starActivity, 就需要再開一個新的task
解決方法就是在startActivity之前指派一個flag給intent 就OK了
Intent it = new Intent(Intent.ACTION_VIEW, uri);
it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(it);
2015年4月10日 星期五
[Android] How to use facebook SDK 4.0.0 to share image.
看圖說故事囉~
新增專案
引入module
Facebook SDK下載位址: https://developers.facebook.com/docs/android 下載後請解壓縮
找到下載的Facebook sdk位址按下確定
Sync一下發現出現問題 ANDROID_BUILD_SDK_VERSION
打開facebook的 build.gradle檔, 將四個變數, 複製到gradle.properties
填入版本, 與app的build.gradle相同就好
再Sync一下, 又有問題了 = ="
這次請打開專案的build.gradle 將classpath的gradle版本從1.1.0修改為1.1.3
打開Project Structure (Ctrl+Alt+Shft+S)
照下圖修改一下
點選app->Dependencies->+號->選擇:facebook->OK
打開Facebook developer網頁 https://developers.facebook.com/apps/
新增一個App
選擇Android
填入你想要命名的app名稱
按下Create App ID
下一步會要求你填入Key Hash
這裡我們要借助剛剛的程式把以下code填到onCreate()裡面,來取得Key Hash (當然你也可以照Facebook guide的建議方式取得): 請注意要修改的地方
PackageInfo info; try { info = getPackageManager().getPackageInfo("com.foxlinkimage.alex.facebooksharedemo", PackageManager.GET_SIGNATURES); for(Signature signature : info.signatures) { MessageDigest md; md =MessageDigest.getInstance("SHA"); md.update(signature.toByteArray()); String KeyResult =new String(Base64.encode(md.digest(), 0));//String something = new String(Base64.encodeBytes(md.digest())); Log.e("hash key", KeyResult); Toast.makeText(MainActivity.this, "My FB Key is \n" + KeyResult, Toast.LENGTH_LONG).show(); } }catch(PackageManager.NameNotFoundException e1){Log.e("name not found", e1.toString()); }catch(NoSuchAlgorithmException e){Log.e("no such an algorithm", e.toString()); }catch(Exception e){Log.e("exception", e.toString());}
DDMS中填入hash key 並Log level改成Error, 接上手機(開啟模擬器), 按下Debug, 會在下面框框跳出你的hash key
回到網頁上填入它吧! 按下一步, 再回到程式開始進行工作
1. 新增權限, 這裡會用到網路和讀取SD卡
2. 在<application>標籤裡填入meta-data
< meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/app_id">在strings.xml新增一個變數app_id, 這個ID就是你剛剛申請時facebook發配給你的, 可以到剛剛那個網頁找到.
往下拉, 新增FacebookActivity和provider, 請注意在provider內後面請改成你的app_id
<activity android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:label="@string/app_name" android:name="com.facebook.FacebookActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar"> <provider android:authorities="com.facebook.app.FacebookContentProvider456793911146084" android:exported="true" android:name="com.facebook.FacebookContentProvider">加入一個按鈕
照key啦~在此僅列出onClick()內的程式碼:
請注意在onCreate()最一開始要先初始化FacebookSdk元件
FacebookSdk.sdkInitialize(getApplicationContext());
Bitmap image = BitmapFactory.decodeFile(path); SharePhoto photo = new SharePhoto.Builder().setBitmap(image).build(); SharePhotoContent content = new SharePhotoContent.Builder().addPhoto(photo).build(); shareDialog.show(content);噫~好了~ 可以用哩
2015年4月8日 星期三
[Android] Android Studio如何引入Facebook SDK
如何導入, 請參考以下連結的文章:
https://trinitytuts.com/integrating-facebook-sdk-application-android-studio/
將Facebook SDK加入後, sync後可能會出現以下訊息:
Could not find property 'ANDROID_BUILD_SDK_VERSION' on project ':facebook'.
請打開 /libraries/facebook/build.gradle
以下四個屬性 請修改成和你的app設置一樣
https://trinitytuts.com/integrating-facebook-sdk-application-android-studio/
將Facebook SDK加入後, sync後可能會出現以下訊息:
Could not find property 'ANDROID_BUILD_SDK_VERSION' on project ':facebook'.
請打開 /libraries/facebook/build.gradle
以下四個屬性 請修改成和你的app設置一樣
compileSdkVersion
buildToolsVersion
minSdkVersion
targetSdkVersion
再次sync後, 我又碰到以下錯誤訊息:
Cannot call getBootClasspath() before setTargetInfo() is called
於是Google後發現是Gradle 1.1.0 plugin 版本的bug, 請參考
http://stackoverflow.com/questions/28689020/cannot-call-getbootclasspath-before-settargetinfo-is-called
解決方法:
打開project的build.gradle
將classpath修改為 'com.android.tools.build:gradle:1.1.2'
再次sync一次就可以了
2015年3月26日 星期四
[Android] 於Fragment加上自訂義的OptionMenu
如果在很多Fragement頁面中, 想要使用各別不同自訂的OptionMenu, 就必須先將
需注意與在Activity使用, 稍稍不太一樣,差異不大, 僅差在有無回傳值
因為Fragment是依附在Activity上, 因此我們必須用getActivity()來取得Context,
才能夠使用Inflater這個東東。
最後我們就可以覆寫onOptionsItemSelected(MenuItem item)來撰寫各個item的處理事件
setHasOptionsMenu(ture)
, 通常會放在onCreate()中, 然後再override onCreateOptionMenu(Menu menu, MenuInflater inflater)
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
getActivity().getMenuInflater().inflate(R.menu.menu_main, menu);
super.onCreateOptionsMenu(menu, inflater);
}
需注意與在Activity使用, 稍稍不太一樣,差異不大, 僅差在有無回傳值
public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return super.onCreateOptionsMenu(menu); }
因為Fragment是依附在Activity上, 因此我們必須用getActivity()來取得Context,
才能夠使用Inflater這個東東。
最後我們就可以覆寫onOptionsItemSelected(MenuItem item)來撰寫各個item的處理事件
public boolean onOptionsItemSelected(MenuItem item) { ...... return super.onOptionsItemSelected(item); }
[Android] Screen rotate issue
這幾天寫App時發現開啟螢幕自動旋轉的功能, 會因為Activity生命週期特性
Activity
running -> onPause() ->
onStop()->onDestroy()->onCreate()->onStrat()->onResume()->Activity
running
Activity會被整個Destroy再重建, 如果畫面有些執行中的東東, 都會被清空到最初始的狀態。
Google後發現有個可暫時頂著用的方法, 但是Google有說這個方法是下下策(有空再找其他方法了XD)
在AndroidManifrest.xml的Activity標籤中加入
android:configChanges="orientation|keyboardHidden|screenSize"
screenSize是在API level 13加入的, 以下說明:
Beginning
with Android 3.2 (API level 13), the "screen size" also changes when
the device switches between
portrait and landscape orientation. Thus, if you want to prevent runtime
restarts due to orientation
change when developing for API level 13 or higher (as declared by the
minSdkVersion and
targetSdkVersion attributes), you must include the "screenSize" value
in addition to the
"orientation" value. That is, you must declare
android:configChanges="orientation|screenSize". However, if your
application targets API
level 12 or lower, then your activity always handles this configuration change
itself (this configuration
change does not restart your activity, even when running on an Android 3.2 or
higher device).
2015年3月9日 星期一
[Android] 官網訓練教學
雖然有點Lag了, 但是找到這個還是很開心, 與其在網路上大海撈針的找文章, 還是先把Google出的訓練文件看一看吧, 裡面有很多細節是一般文章有忽略的喔!!
http://developer.android.com/training/index.html
http://developer.android.com/training/index.html
2015年3月5日 星期四
[Android] GridView練習
看網路上的教學寫了一個小程式, 利用GridView列出所有在Drawable裡面的圖片(這裡放入12生肖圖), 點入其中一張圖跳轉到另一個Activity顯示完整的圖, 原本是想在這個Activity做Crop的動作, 但是還在找相關的教學文章, 所以還沒有implement
MainActivity.java
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity">
<GridView android:id="@+id/main_page_gridview"
android:numColumns="auto_fit"
android:gravity="center"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
activity_full_image.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.foxlinkimage.alex.gridviewtest.FullImage"
android:id="@+id/relayout">
<ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout android:layout_below="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button android:id="@+id/crop"
android:text="Crop"
android:textSize="15sp"
android:layout_width="80dp"
android:layout_height="40dp" />
</LinearLayout>
</RelativeLayout>
grid_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/image" android:layout_marginTop="10dp" android:layout_width="100dp" android:layout_height="100dp" /> <TextView android:id="@+id/text" android:textSize="12sp" android:gravity="center" android:paddingTop="10dp" android:paddingBottom="10dp" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
MainActivity.java
public class MainActivity extends ActionBarActivity { private GridView gridView; public static int[] image = { R.drawable.mouse, R.drawable.cow, R.drawable.tiger, R.drawable.rabbit, R.drawable.dragon, R.drawable.snake, R.drawable.horse, R.drawable.goat, R.drawable.monkey, R.drawable.chicken, R.drawable.dog, R.drawable.pig }; private String[] imgText = {"鼠","牛","虎","兔","龍","蛇","馬","羊","猴","雞","狗","豬"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListFullImage.java
public class FullImage extends ActionBarActivity { ImageView image; int image_index; Drawable drawable; Resources res; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_full_image); image = (ImageView)findViewById(R.id.image); image_index = getIntent().getExtras().getInt("img"); res = getBaseContext().getResources(); drawable = res.getDrawable(MainActivity.image[image_index]); image.setImageDrawable(drawable); }activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity">
<GridView android:id="@+id/main_page_gridview"
android:numColumns="auto_fit"
android:gravity="center"
android:columnWidth="100dp"
android:stretchMode="columnWidth"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
activity_full_image.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context="com.foxlinkimage.alex.gridviewtest.FullImage"
android:id="@+id/relayout">
<ImageView android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout android:layout_below="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button android:id="@+id/crop"
android:text="Crop"
android:textSize="15sp"
android:layout_width="80dp"
android:layout_height="40dp" />
</LinearLayout>
</RelativeLayout>
grid_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/image" android:layout_marginTop="10dp" android:layout_width="100dp" android:layout_height="100dp" /> <TextView android:id="@+id/text" android:textSize="12sp" android:gravity="center" android:paddingTop="10dp" android:paddingBottom="10dp" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
2015年2月12日 星期四
[Android] 將imageView裡的圖片存入自建的圖片Folder
File publicPicFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File customCreateFolder = new File(publicPicFolder, "MyPicFolder");
customCreateFolder.mkdirs();
File save_image = new File(customCreateFolder,"save_img.jpg");
FileOutputStream fos;
imgView.setDrawingCacheEnabled(true);
Bitmap bmp = imgView.getDrawingCache();
try{
save_image.createNewFile();
fos = new FileOutputStream(save_image);
bmp.compress(Bitmap.CompressFormat.JPEG,100,fos);
fos.flush();
fos.close();
}catch(Exception e)
{
e.printStackTrace();
}
2015年2月9日 星期一
[Android] 下載圖片 from Internet
目前survey到有兩種方法(第二種簡單許多了 噗~)
//Method1: Use HTTP protocol POST to retrieve a image
HttpURLConnection con = (HttpURLConnection)(new URL(url)).openConnection();
con.setRequestMethod("GET");
con.setDoInput(true);
con.setDoOutput(true);
con.connect();
InputStream iis = new BufferedInputStream(con.getInputStream());
bitmap = BitmapFactory.decodeStream(iis);
//Method2
bitmap = BitmapFactory.decodeStream((InputStream)new URL(url).getContent());
使用時需要記得在AndroidManifest.xml 加入使用網路的權限
<uses-permission android:name="android.permission.INTERNET" />
//Method1: Use HTTP protocol POST to retrieve a image
HttpURLConnection con = (HttpURLConnection)(new URL(url)).openConnection();
con.setRequestMethod("GET");
con.setDoInput(true);
con.setDoOutput(true);
con.connect();
InputStream iis = new BufferedInputStream(con.getInputStream());
bitmap = BitmapFactory.decodeStream(iis);
//Method2
bitmap = BitmapFactory.decodeStream((InputStream)new URL(url).getContent());
使用時需要記得在AndroidManifest.xml 加入使用網路的權限
<uses-permission android:name="android.permission.INTERNET" />
2015年2月8日 星期日
[Android] Download via HTTP "GET" "POST" (轉載)
Android HTTP Client: GET, POST, Download, Upload, Multipart Request
HTTP connection
Post request
Download data
Upload data
Multipart request
As a server we will use three simple Servlet running inside Tomcat 7.0. We won't cover how to create a Servlet using API 3.0, you can find the source code here.
GET And POST Requests
GET and POST requests are the base blocks in HTTP protocol. To make this kind of requests we need first to open a connection toward the remove server:
1
2
3
4
5
| HttpURLConnection con = (HttpURLConnection) ( new URL(url)).openConnection(); con.setRequestMethod( "POST" ); con.setDoInput( true ); con.setDoOutput( true ); con.connect(); |
In the first line we get the HttpURLConnection, while in the line 2 we set the method and at the end we connect to the server.
Once we have opened the connection we can write on it using the OutputStream.
1
| con.getOutputStream().write( ( "name=" + name).getBytes()); |
As we already know parameters are written using key value pair.
The last step is reading the response, using the InputStream:
1
2
3
4
5
| InputStream is = con.getInputStream(); byte [] b = new byte [ 1024 ]; while ( is.read(b) != - 1 ) buffer.append( new String(b)); con.disconnect(); |
Everything is very simple by now, but we have to remember one thing: making an HTTP connection is a time consuming operation that could require long time sometime so we can't run it in the main thread otherwise we could get a ANR problem. To solve it we can use an AsyncTask.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| private class SendHttpRequestTask extends AsyncTask<String, Void, String>{ @Override protected String doInBackground(String... params) { String url = params[ 0 ]; String name = params[ 1 ]; String data = sendHttpRequest(url, name); return data; } @Override protected void onPostExecute(String result) { edtResp.setText(result); item.setActionView( null ); } } |
Running the app we get:
![]() | ![]() |
As we can see we post a name to the server and it responds with the classic ‘Hello….’. On the server side we can check that the server received correctly our post parameter:

Download Data From Server
One of the most common scenario is when an Android App has to download some data from a remote sever. We can suppose that we want to download an image from the server. In this case we have always to use an AsyncTask to complete our operation, the code is shown below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| public byte [] downloadImage(String imgName) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { System.out.println( "URL [" +url+ "] - Name [" +imgName+ "]" ); HttpURLConnection con = (HttpURLConnection) ( new URL(url)).openConnection(); con.setRequestMethod( "POST" ); con.setDoInput( true ); con.setDoOutput( true ); con.connect(); con.getOutputStream().write( ( "name=" + imgName).getBytes()); InputStream is = con.getInputStream(); byte [] b = new byte [ 1024 ]; while ( is.read(b) != - 1 ) baos.write(b); con.disconnect(); } catch (Throwable t) { t.printStackTrace(); } return baos.toByteArray(); } |
This method is called in this way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| private class SendHttpRequestTask extends AsyncTask<String, Void, byte []> { @Override protected byte [] doInBackground(String... params) { String url = params[ 0 ]; String name = params[ 1 ]; HttpClient client = new HttpClient(url); byte [] data = client.downloadImage(name); return data; } @Override protected void onPostExecute( byte [] result) { Bitmap img = BitmapFactory.decodeByteArray(result, 0 , result.length); imgView.setImageBitmap(img); item.setActionView( null ); } } |
Running the app we have:

Upload Data To The Server Using MultipartRequest
This the most complex part in handling http connection. Natively HttpURLConnection doesn’t handle this type of request. It can happen that an Android App has to upload some binary data to the server. It can be that an app has to upload an image for example. In this case the request get more complex, because a “normal” request isn’t enough. We have to create a MultipartRequest.
A MultipartRequest is a request that is made by different parts like parameters and binary data. How can we handle this request?
Well the first step is opening a connection informing the server we wants to send some binary info:
1
2
3
4
5
6
7
8
9
10
| public void connectForMultipart() throws Exception { con = (HttpURLConnection) ( new URL(url)).openConnection(); con.setRequestMethod( "POST" ); con.setDoInput( true ); con.setDoOutput( true ); con.setRequestProperty( "Connection" , "Keep-Alive" ); con.setRequestProperty( "Content-Type" , "multipart/form-data; boundary=" + boundary); con.connect(); os = con.getOutputStream(); } |
In the line 6 and 7 we specify the request content-type and another field called boundary. This field is a char sequence used to separate different parts.
For each part we want to add we need to specify if it is text part like post parameter or it is a file (so binary data).
1
2
3
4
5
6
7
8
9
10
11
| public void addFormPart(String paramName, String value) throws Exception { writeParamData(paramName, value); } private void writeParamData(String paramName, String value) throws Exception { os.write( (delimiter + boundary + "\r\n" ).getBytes()); os.write( "Content-Type: text/plain\r\n" .getBytes()); os.write( ( "Content-Disposition: form-data; name=\"" + paramName + "\"\r\n" ).getBytes());; os.write( ( "\r\n" + value + "\r\n" ).getBytes()); } |
where
1
2
| private String delimiter = "--" ; private String boundary = "SwA" +Long.toString(System.currentTimeMillis())+ "SwA" ; |
1
2
3
4
5
6
7
8
9
10
11
| public void addFilePart(String paramName, String fileName, byte [] data) throws Exception { os.write( (delimiter + boundary + "\r\n" ).getBytes()); os.write( ( "Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + fileName + "\"\r\n" ).getBytes()); os.write( ( "Content-Type: application/octet-stream\r\n" ).getBytes()); os.write( ( "Content-Transfer-Encoding: binary\r\n" ).getBytes()); os.write( "\r\n" .getBytes()); os.write(data); os.write( "\r\n" .getBytes()); } |
So in our app we have:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| private class SendHttpRequestTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { String url = params[ 0 ]; String param1 = params[ 1 ]; String param2 = params[ 2 ]; Bitmap b = BitmapFactory.decodeResource(UploadActivity. this .getResources(), R.drawable.logo); ByteArrayOutputStream baos = new ByteArrayOutputStream(); b.compress(CompressFormat.PNG, 0 , baos); try { HttpClient client = new HttpClient(url); client.connectForMultipart(); client.addFormPart( "param1" , param1); client.addFormPart( "param2" , param2); client.addFilePart( "file" , "logo.png" , baos.toByteArray()); client.finishMultipart(); String data = client.getResponse(); } catch (Throwable t) { t.printStackTrace(); } return null ; } @Override protected void onPostExecute(String data) { item.setActionView( null ); } } |
Running it we have:
![]() | ![]() |
Source code for server side servlet here
訂閱:
文章 (Atom)