Ⅰ 怎樣實現在android實現帶進度條的上傳效果
實現在android實現帶進度條的上傳效果效果如圖:用到以下兩個類就可實現帶進度條的文件上傳:
1、CustomMultiPartEntity extends MultipartEntity,
2、HttpMultipartPost extends AsyncTask
代碼如下:
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
public class CustomMultipartEntity extends MultipartEntity {
private final ProgressListener listener;
public CustomMultipartEntity(final ProgressListener listener) {
super();
this.listener = listener;
}
public CustomMultipartEntity(final HttpMultipartMode mode, final ProgressListener listener) {
super(mode);
this.listener = listener;
}
public CustomMultipartEntity(HttpMultipartMode mode, final String boundary,
final Charset charset, final ProgressListener listener) {
super(mode, boundary, charset);
this.listener = listener;
}
@Override
public void writeTo(final OutputStream outstream) throws IOException {
super.writeTo(new CountingOutputStream(outstream, this.listener));
}
public static interface ProgressListener {
void transferred(long num);
}
public static class CountingOutputStream extends FilterOutputStream {
private final ProgressListener listener;
private long transferred;
public CountingOutputStream(final OutputStream out, final ProgressListener listener) {
super(out);
this.listener = listener;
this.transferred = 0;
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
this.transferred += len;
this.listener.transferred(this.transferred);
}
public void write(int b) throws IOException {
out.write(b);
this.transferred++;
this.listener.transferred(this.transferred);
}
}
}
該類計算寫入的位元組數,我們需要在實現ProgressListener中的trasnfered()方法,更行進度條
public class HttpMultipartPost extends AsyncTask<HttpResponse, Integer, TypeUploadImage> {
ProgressDialogpd;
longtotalSize;
@Override
protectedvoidonPreExecute(){
pd= newProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Uploading Picture...");
pd.setCancelable(false);
pd.show();
}
@Override
(HttpResponse... arg0) {
HttpClienthttpClient = newDefaultHttpClient();
HttpContexthttpContext = newBasicHttpContext();
HttpPosthttpPost = newHttpPost("http://herpderp.com/UploadImage.php");
try{
= newCustomMultipartEntity(
newProgressListener() {
@Override
public void transferred(longnum){
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
// We use FileBody to transfer an image
multipartContent.addPart("uploaded_file", newFileBody(
newFile(m_userSelectedImagePath)));
totalSize= multipartContent.getContentLength();
// Send it
httpPost.setEntity(multipartContent);
HttpResponseresponse = httpClient.execute(httpPost, httpContext);
String serverResponse = EntityUtils.toString(response.getEntity());
ResponseFactoryrp = newResponseFactory(serverResponse);
return(TypeImage) rp.getData();
}
catch(Exception e) {
System.out.println(e);
}
returnnull;
}
@Override
protectedvoidonProgressUpdate(Integer... progress){
pd.setProgress((int) (progress[0]));
}
@Override
protectedvoidonPostExecute(TypeUploadImageui) {
pd.dismiss();
}
}
在 transferred()函數中調用publishProgress((int) ((num / (float) totalSize) * 100));
在onProgressUpdate()實現上傳進度的更新操作
Ⅱ android 進行https訪問時為什麼總是返回400錯誤,一般是什麼原因
地址不存在,通過電腦上一下看能訪問到網址么,不能的話是網站問題,能的話可能是你程序上寫的地址不對或者參數不對
Ⅲ 如何提升Android開發效率
筆者在經歷了多個Android開發項目之後,個人積累也從別處學習了很多在Android開發中非常實用的小經驗。下面從中選擇了最實用的16條,分享給大家。
1.TextView中的getTextSize返回值是以像素(px)為單位的,而setTextSize()是以sp為單位的.所以如果直接用返回的值來設置會出錯,解決辦法是用setTextSize()的另外一種形式,可以指定單位:
1
2
3
4
<span style="font-size:16px;">setTextSize(int unit, int size)
TypedValue.COMPLEX_UNIT_PX : Pixels
TypedValue.COMPLEX_UNIT_SP : Scaled Pixels
TypedValue.COMPLEX_UNIT_DIP : Device Independent Pixels</span>
2.在繼承自View時,繪制bitmap時,需要將圖片放到新建的drawable-xdpi中,否則容易出現繪制大小發生改變。
3.在文字中加下劃線: textView.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG)。
4.scrollView是繼承自frameLayout,所以在使用LayoutParams時需要用frameLayout的。
5.在Android中幾種網路編程的方式:
(1)針對TCP/IP的Socket、ServerSocket
(2)針對UDP的DatagramSocket、DatagramPackage。這里需要注意的是,考慮到Android設備通常是手持終端,IP都是隨著上網進行分配的。不是固定的。因此開發也是有 一點與普通互聯網應用有所差異的。
(3)針對直接URL的HttpURLConnection
(4)Google 集成了Apache HTTP客戶端,可使用HTTP進行網路編程。針對HTTP,Google集成了Appache Http core和httpclient 4版本,因此特別注意Android不支持 httpclient 3.x系列,而且目前並不支持Multipart(MIME),需要自行添加httpmime.jar
(5)使用Web Service。Android可以通過開源包如jackson去支持Xmlrpc和Jsonrpc,另外也可以用Ksoap2去實現Webservice
(6) 直接使用WebView視圖組件顯示網頁。基於WebView 進行開發,Google已經提供了一個基於chrome-lite的Web瀏覽器,直接就可以進行上網瀏覽網頁。
6.TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
這個是我們最常用的一個構造方法,
float fromXDelta:這個參數表示動畫開始的點離當前View X坐標上的差值;
float toXDelta, 這個參數表示動畫結束的點離當前View X坐標上的差值;
float fromYDelta, 這個參數表示動畫開始的點離當前View Y坐標上的差值;
float toYDelta)這個參數表示動畫開始的點離當前View Y坐標上的差值;
如果view在A(x,y)點 那麼動畫就是從B點(x+fromXDelta, y+fromYDelta)點移動到C 點 (x+toXDelta,y+toYDelta)點。
7.android提供了幾種在其他線程中訪問UI線程的方法
Ⅳ android中mediamuxer和mediacodec的區別
Android中MediaMuxer和MediaCodec用例
在Android的多媒體類中,MediaMuxer和MediaCodec算是比較年輕的,它們是JB 4.1和JB 4.3才引入的。前者用於將音頻和視頻進行混合生成多媒體文件。缺點是目前只能支持一個audio track和一個video track,而且僅支持mp4輸出。不過既然是新生事物,相信之後的版本應該會有大的改進。MediaCodec用於將音視頻進行壓縮編碼,它有個比較牛X的地方是可以對Surface內容進行編碼,如KK 4.4中屏幕錄像功能就是用它實現的。
注意它們和其它一些多媒體相關類的關系和區別:MediaExtractor用於音視頻分路,和MediaMuxer正好是反過程。MediaFormat用於描述多媒體數據的格式。MediaRecorder用於錄像+壓縮編碼,生成編碼好的文件如mp4, 3gpp,視頻主要是用於錄制Camera preview。MediaPlayer用於播放壓縮編碼後的音視頻文件。AudioRecord用於錄制PCM數據。AudioTrack用於播放PCM數據。PCM即原始音頻采樣數據,可以用如vlc播放器播放。當然了,通道采樣率之類的要自己設,因為原始采樣數據是沒有文件頭的,如:
vlc --demux=rawaud --rawaud-channels 2 --rawaud-samplerate 44100 audio.pcm
回到MediaMuxer和MediaCodec這兩個類,它們的參考文檔見http://developer.android.com/reference/android/media/MediaMuxer.html和http://developer.android.com/reference/android/media/MediaCodec.html,里邊有使用的框架。這個組合可以實現很多功能,比如音視頻文件的編輯(結合MediaExtractor),用OpenGL繪制Surface並生成mp4文件,屏幕錄像以及類似Camera app里的錄像功能(雖然這個用MediaRecorder更合適)等。
這里以一個很無聊的功能為例,就是在一個Surface上畫圖編碼生成視頻,同時用MIC錄音編碼生成音頻,然後將音視頻混合生成mp4文件。程序本身沒什麼用,但是示例了MediaMuxer和MediaCodec的基本用法。本程序主要是基於兩個測試程序:一個是Grafika中的SoftInputSurfaceActivity和HWEncoderExperiments。它們一個是生成視頻,一個生成音頻,這里把它們結合一下,同時生成音頻和視頻。基本框架和流程如下:
首先是錄音線程,主要參考HWEncoderExperiments。通過AudioRecord類接收來自麥克風的采樣數據,然後丟給Encoder准備編碼:
AudioRecord audio_recorder;
audio_recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT, buffer_size);
// ...
audio_recorder.startRecording();
while (is_recording) {
byte[] this_buffer = new byte[frame_buffer_size];
read_result = audio_recorder.read(this_buffer, 0, frame_buffer_size); // read audio raw data
// …
presentationTimeStamp = System.nanoTime() / 1000;
audioEncoder.offerAudioEncoder(this_buffer.clone(), presentationTimeStamp); // feed to audio encoder
}
這里也可以設置AudioRecord的回調(通過())來觸發音頻數據的讀取。offerAudioEncoder()里主要是把audio采樣數據送入音頻MediaCodec的InputBuffer進行編碼:
ByteBuffer[] inputBuffers = mAudioEncoder.getInputBuffers();
int inputBufferIndex = mAudioEncoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(this_buffer);
...
mAudioEncoder.queueInputBuffer(inputBufferIndex, 0, this_buffer.length, presentationTimeStamp, 0);
}
下面,參考Grafika-SoftInputSurfaceActivity,並加入音頻處理。主循環大體分四部分:
try {
// Part 1
prepareEncoder(outputFile);
...
// Part 2
for (int i = 0; i < NUM_FRAMES; i++) {
generateFrame(i);
drainVideoEncoder(false);
drainAudioEncoder(false);
}
// Part 3
...
drainVideoEncoder(true);
drainAudioEncoder(true);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
} finally {
// Part 4
releaseEncoder();
}
第1部分是准備工作,除了video的MediaCodec,這里還初始化了audio的MediaCodec:
MediaFormat audioFormat = new MediaFormat();
audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100);
audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
...
mAudioEncoder = MediaCodec.createEncoderByType(AUDIO_MIME_TYPE);
mAudioEncoder.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mAudioEncoder.start();
第2部分進入主循環,app在Surface上直接繪圖,由於這個Surface是從MediaCodec中用createInputSurface()申請來的,所以畫完後不用顯式用queueInputBuffer()交給Encoder。drainVideoEncoder()和drainAudioEncoder()分別將編碼好的音視頻從buffer中拿出來(通過dequeueOutputBuffer()),然後交由MediaMuxer進行混合(通過writeSampleData())。注意音視頻通過PTS(Presentation time stamp,決定了某一幀的音視頻數據何時顯示或播放)來同步,音頻的time stamp需在AudioRecord從MIC採集到數據時獲取並放到相應的bufferInfo中,視頻由於是在Surface上畫,因此直接用dequeueOutputBuffer()出來的bufferInfo中的就行,最後將編碼好的數據送去MediaMuxer進行多路混合。
注意這里Muxer要等把audio track和video track都加入了再開始。MediaCodec在一開始調用dequeueOutputBuffer()時會返回一次INFO_OUTPUT_FORMAT_CHANGED消息。我們只需在這里獲取該MediaCodec的format,並注冊到MediaMuxer里。接著判斷當前audio track和video track是否都已就緒,如果是的話就啟動Muxer。
總結來說,drainVideoEncoder()的主邏輯大致如下,drainAudioEncoder也是類似的,只是把video的MediaCodec換成audio的MediaCodec即可。
while(true) {
int encoderStatus = mVideoEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
...
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
encoderOutputBuffers = mVideoEncoder.getOutputBuffers();
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
MediaFormat newFormat = mAudioEncoder.getOutputFormat();
mAudioTrackIndex = mMuxer.addTrack(newFormat);
mNumTracksAdded++;
if (mNumTracksAdded == TOTAL_NUM_TRACKS) {
mMuxer.start();
}
} else if (encoderStatus < 0) {
...
} else {
ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
...
if (mBufferInfo.size != 0) {
mMuxer.writeSampleData(mVideoTrackIndex, encodedData, mBufferInfo);
}
mVideoEncoder.releaseOutputBuffer(encoderStatus, false);
if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
break;
}
}
}
第3部分是結束錄制,發送EOS信息,這樣在drainVideoEncoder()和drainAudioEncoder中就可以根據EOS退出內循環。第4部分為清理工作。把audio和video的MediaCodec,MediaCodec用的Surface及MediaMuxer對象釋放。
最後幾點注意:
1. 在AndroidManifest.xml里加上錄音許可權,否則創建AudioRecord對象時鐵定失敗:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
2. 音視頻通過PTS同步,兩個的單位要一致。
3. MediaMuxer的使用要按照Constructor -> addTrack -> start -> writeSampleData -> stop 的順序。如果既有音頻又有視頻,在stop前兩個都要writeSampleData()過。
Code references:
Grafika: https://github.com/google/grafika
Bigflake: http://bigflake.com/mediacodec/
HWEncoderExperiments:https://github.com/OnlyInAmerica/HWEncoderExperiments/tree/audioonly/HWEncoderExperiments/src/main/java/net/openwatch/hwencoderexperiments
Android test:http://androidxref.com/4.4.2_r2/xref/cts/tests/tests/media/src/android/media/cts/
http://androidxref.com/4.4.2_r2/xref/pdk/apps/TestingCamera2/src/com/android/testingcamera2/CameraRecordingStream.java