项目作者: qiniu

项目描述 :
适用于Android的Qiniu资源(云)存储SDK
高级语言: Java
项目地址: git://github.com/qiniu/android-sdk.git
创建时间: 2012-08-06T01:34:03Z
项目社区:https://github.com/qiniu/android-sdk

开源协议:MIT License

下载


Qiniu Resource Storage SDK for Android

@qiniu on weibo
Software License
Build Status
codecov
Latest Stable Version

演示代码

https://github.com/qiniudemo/qiniu-lab-android

安装

运行环境

Qiniu SDK 版本 最低 Android版本 依赖库版本
8.9.x Android 4.0+ okhttp 4+
8.8.x Android 4.0+ okhttp 4+
8.7.x Android 4.0+ okhttp 4+
8.6.x Android 4.0+ okhttp 4+
8.5.x Android 4.0+ okhttp 4+
8.4.x Android 4.0+ okhttp 4+
8.3.2 Android 4.0+ okhttp 4+
8.3.1 Android 4.0+ okhttp 4+
8.3.0 Android 5.0+ okhttp 4+
8.2.x Android 5.0+ okhttp 4+
8.1.x Android 5.0+ okhttp 4+
8.0.x Android 5.0+ okhttp 4+
7.7.x Android 5.0+ okhttp 4+
7.6.x Android 5.0+ okhttp 4+
7.5.x Android 5.0+ okhttp 4+
7.4.6 Android 4.0+ okhttp 3.12.6
7.3.x Android 2.3+ okhttp 3.11.0
7.2.x Android 2.3+ okhttp 3+
7.1.x Android 2.3+ okhttp 2.6+
7.0.8,7.0.9 Android 2.2+ android-async-http 1.4.9
7.0.7 Android 2.2+ android-async-http 1.4.8

注意

  • 推荐使用最新版:8.9.1
  • 7.6.2 ~ 8.3.2 AndroidNetwork.getMobileDbm()可以获取手机信号强度,需要如下权限(API>=18时生效)
    1. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    2. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
  • 从7.5.0开始增加了DNS预取和缓存策略,减少dns解析错误
  • 如果可以明确 区域 的话,最好指定固定区域,这样可以少一步网络请求,少一步出错的可能。
  • 如果使用 Android 4.x ,对应 okhttp 版本请调整至 3.12.+

直接安装

将sdk jar文件 复制到项目中去,jar包下载地址 , 下载对应的jar包,以及搜索下载对应的依赖库

happy-dns下载地址

通过maven

  • Android Studio中添加dependencies 或者 在项目中添加maven依赖
    ```
    // 1. 直接导入
    implementation ‘com.qiniu:qiniu-android-sdk:8.9.+’

// 2. 如果要修改okhttp依赖的版本,可采用以下方式(强烈建议使用七牛库依赖的okhttp版本)
implementation (‘com.qiniu:qiniu-android-sdk:8.9.+’){
exclude (group: ‘com.squareup.okhttp3’, module: ‘okhttp’)
}
implementation ‘com.squareup.okhttp3:okhttp:4.9.1’

  1. * 如果是eclipse, 也可以直接添加依赖来处理。
  2. ## 使用方法
  3. UploadManager 可以创建一次,一直使用。
  4. 7.6.2 ~ 8.3.2 会调用AndroidNetwork.getMobileDbm可以获取网络信号强度
  5. 需要Manifest.permission.ACCESS_FINE_LOCATIONManifest.permission.ACCESS_COARSE_LOCATION权限
  6. ```java
  7. import com.qiniu.android.storage.UploadManager;
  8. ...
  9. String token = "从服务端SDK获取";
  10. UploadManager uploadManager = new UploadManager();
  11. uploadManager.put("Hello, World!".getBytes(), "hello", token,
  12. new UpCompletionHandler() {
  13. @Override
  14. public void complete(String key, ResponseInfo info, JSONObject response) {
  15. LogUtil.i(info);
  16. }
  17. }, null);
  18. ...

支持使用 HTTP/3 协议发起请求

导入 HTTP/3 client 插件,http3 client 插件依赖于 Android SDK v8.5.0及以上版本

安装导入

  1. // 移除 qiniu-android-sdk 依赖 : implementation 'com.qiniu:qiniu-android-sdk:x.x.+'
  2. implementation 'com.qiniu:qiniu-android-curl-plugin:1.0.0'

使用 CurlClient

  1. import com.qiniu.client.curl.CurlClient;
  2. import com.qiniu.android.storage.Configuration;
  3. import com.qiniu.android.storage.UploadManager;
  4. // @param caPath: SSL 证书本地路径;如果想自定义 CA 可设置此选项,此处为 CA 文件的本地路径。
  5. // 如果未定义(caPath 配置 null)则使用 SDK 内部提供的 CA 证书,证书来源:https://curl.se/ca/cacert.pem
  6. CurlClient client = new CurlClient(caPath);
  7. Configuration config = new Configuration.Builder()
  8. .requestClient(client)
  9. .build();
  10. UploadManager manager = new UploadManager(config);

测试

  1. $ ./gradlew connectedAndroidTest

常见问题

1).有关Android Studio以及Eclipse安装运行Android Demo步骤,这里以Android Studio为实例:
1.修改 build.gradle
双击打开您的工程目录下的build.gradle,在dependencies中添加一条依赖compile ‘com.qiniu:qiniu-android-sdk:7.2.+’,如下所示:

  1. dependencies {
  2. compile fileTree(dir: 'libs', include: ['*.jar'])
  3. testCompile 'junit:junit:4.12'
  4. compile 'com.android.support:appcompat-v7:23.1.1'
  5. compile 'com.qiniu:qiniu-android-sdk:7.6.+'
  6. }

当然也可以将jar包下载到本地导入到项目中

2.添加相关权限,在 app/src/main 目录中的 AndroidManifest.xml 中增加如下 uses-permission 声明

  1. <uses-permission android:name="android.permission.INTERNET"></uses-permission>
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ></uses-permission>

3.布局,在res/layout/activity_main.xml添加相应的上传的按钮以及相关控件,以下以一个简单的布局为例:

  1. <TextView
  2. android:layout_width="wrap_content"
  3. android:layout_height="wrap_content"
  4. android:layout_centerHorizontal="true"
  5. android:textSize="20sp"
  6. android:layout_marginTop="10dp"
  7. android:text="七牛云存储 SDK"
  8. android:id="@+id/textView"
  9. android:layout_alignParentTop="true"
  10. ></TextView>
  11. <Button
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:text="上传"
  15. android:id="@+id/button"
  16. android:layout_centerHorizontal="true"
  17. android:layout_centerVertical="true"></Button>

效果如下:
这里写图片描述

4.逻辑代码, 为按钮添加上传事件,这里以上传一个byte数组为例,另外,上传的数据可以是文件路径或者文件,以下给出具体的代码:

  1. package com.dxy.cloud.myapplication;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.util.Log;
  5. import android.view.View;
  6. import android.widget.Button;
  7. import android.widget.TextView;
  8. import com.qiniu.android.http.ResponseInfo;
  9. import com.qiniu.android.storage.UpCompletionHandler;
  10. import com.qiniu.android.storage.UploadManager;
  11. import com.qiniu.android.storage.UploadOptions;
  12. import org.json.JSONObject;
  13. public class MainActivity extends Activity implements View.OnClickListener {
  14. //指定upToken, 强烈建议从服务端提供get请求获取, 这里为了掩饰直接指定key
  15. public static String uptoken = "xxxxx:xxxxx:xxxxx";
  16. private Button btnUpload;
  17. private TextView textView;
  18. private UploadManager uploadManager;
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_main);
  23. textView = (TextView) findViewById(R.id.textView);
  24. btnUpload = (Button) findViewById(R.id.button);
  25. btnUpload.setOnClickListener(this);
  26. //new一个uploadManager类
  27. uploadManager = new UploadManager();
  28. }
  29. @Override
  30. public void onClick(View v) {
  31. LogUtil.i("starting......");
  32. byte[] data=new byte[]{ 0, 1, 2, 3};
  33. //设置上传后文件的key
  34. String upkey = "uploadtest.txt";
  35. uploadManager.put(data, upkey, uptoken, new UpCompletionHandler() {
  36. public void complete(String key, ResponseInfo rinfo, JSONObject response) {
  37. btnUpload.setVisibility(View.INVISIBLE);
  38. String s = key + ", " + rinfo + ", " + response;
  39. LogUtil.i(s);
  40. textView.setTextSize(10);
  41. String o = textView.getText() + "\r\n\r\n";
  42. //显示上传后文件的url
  43. textView.setText(o + s + "\n" + "http://xm540.com1.z0.glb.clouddn.com/" + key);
  44. }
  45. }, new UploadOptions(null, "test-type", true, null, null));
  46. }
  47. }

运行的效果图如下:
这里写图片描述

2).有关断点续传,暂停上传,设置自定义变量的用法,这里以一个简单的Demo给出下实现的方法,这里的Demo主要实现从相册选择一张图片上传来说明。

可以参考放GitHub(Android Studio)上的源码: https://github.com/clouddxy/AndroidDemo
这里直接给出MainActivity中的代码:

  1. package com.dxy.cloud.myapplication;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.database.Cursor;
  5. import android.graphics.BitmapFactory;
  6. import android.net.Uri;
  7. import android.os.Bundle;
  8. import android.provider.MediaStore;
  9. import android.util.Log;
  10. import android.view.View;
  11. import android.view.View.OnClickListener;
  12. import android.widget.Button;
  13. import android.widget.ImageView;
  14. import android.widget.ProgressBar;
  15. import android.widget.TextView;
  16. import com.qiniu.android.http.ResponseInfo;
  17. import com.qiniu.android.storage.Configuration;
  18. import com.qiniu.android.storage.KeyGenerator;
  19. import com.qiniu.android.storage.Recorder;
  20. import com.qiniu.android.storage.UpCancellationSignal;
  21. import com.qiniu.android.storage.UpCompletionHandler;
  22. import com.qiniu.android.storage.UpProgressHandler;
  23. import com.qiniu.android.storage.UploadManager;
  24. import com.qiniu.android.storage.UploadOptions;
  25. import com.qiniu.android.storage.persistent.FileRecorder;
  26. import com.qiniu.android.utils.UrlSafeBase64;
  27. import org.json.JSONObject;
  28. import java.io.BufferedReader;
  29. import java.io.File;
  30. import java.io.FileNotFoundException;
  31. import java.io.FileReader;
  32. import java.io.IOException;
  33. import java.util.HashMap;
  34. public class MainActivity extends Activity {
  35. private Button button1;
  36. private Button button2;
  37. private Button button3;
  38. private ImageView imageview;
  39. private Uri imageUri;
  40. private TextView textview;
  41. private ProgressBar progressbar;
  42. public static final int RESULT_LOAD_IMAGE = 1;
  43. private volatile boolean isCancelled = false;
  44. UploadManager uploadManager;
  45. public MainActivity() {
  46. //断点上传
  47. String dirPath = "/storage/emulated/0/Download";
  48. Recorder recorder = null;
  49. try{
  50. File f = File.createTempFile("qiniu_xxxx", ".tmp");
  51. LogUtil.d(f.getAbsolutePath().toString());
  52. dirPath = f.getParent();
  53. //设置记录断点的文件的路径
  54. recorder = new FileRecorder(dirPath);
  55. } catch(Exception e) {
  56. e.printStackTrace();
  57. }
  58. final String dirPath1 = dirPath;
  59. //默认使用 key 的url_safe_base64编码字符串作为断点记录文件的文件名。
  60. //避免记录文件冲突(特别是key指定为null时),也可自定义文件名(下方为默认实现):
  61. KeyGenerator keyGen = new KeyGenerator(){
  62. public String gen(String key, File file){
  63. // 不必使用url_safe_base64转换,uploadManager内部会处理
  64. // 该返回值可替换为基于key、文件内容、上下文的其它信息生成的文件名
  65. String path = key + "_._" + new StringBuffer(file.getAbsolutePath()).reverse();
  66. LogUtil.d(path);
  67. File f = new File(dirPath1, UrlSafeBase64.encodeToString(path));
  68. BufferedReader reader = null;
  69. try {
  70. reader = new BufferedReader(new FileReader(f));
  71. String tempString = null;
  72. int line = 1;
  73. try {
  74. while ((tempString = reader.readLine()) != null) {
  75. // System.out.println("line " + line + ": " + tempString);
  76. LogUtil.d("line " + line + ": " + tempString);
  77. line++;
  78. }
  79. } catch (IOException e) {
  80. // TODO Auto-generated catch block
  81. e.printStackTrace();
  82. } finally {
  83. try{
  84. reader.close();
  85. } catch(Exception e) {
  86. e.printStackTrace();
  87. }
  88. }
  89. } catch (FileNotFoundException e) {
  90. // TODO Auto-generated catch block
  91. e.printStackTrace();
  92. }
  93. return path;
  94. }
  95. };
  96. Configuration config = new Configuration.Builder()
  97. // recorder 分片上传时,已上传片记录器
  98. // keyGen 分片上传时,生成标识符,用于片记录器区分是那个文件的上传记录
  99. .recorder(recorder, keyGen)
  100. .build();
  101. // 实例化一个上传的实例
  102. uploadManager = new UploadManager(config);
  103. }
  104. @Override
  105. protected void onCreate(Bundle savedInstanceState) {
  106. super.onCreate(savedInstanceState);
  107. setContentView(R.layout.activity_main);
  108. button1 = (Button) findViewById(R.id.bt1);
  109. button2 = (Button) findViewById(R.id.bt2);
  110. button3 = (Button) findViewById(R.id.bt3);
  111. imageview = (ImageView) findViewById(R.id.iv);
  112. textview = (TextView) findViewById(R.id.tv);
  113. progressbar = (ProgressBar) findViewById(R.id.pb);
  114. // final String token = edittext.getText().toString();
  115. button1.setOnClickListener(new OnClickListener() {
  116. @Override
  117. public void onClick(View v) {
  118. Intent i = new Intent(
  119. Intent.ACTION_PICK,
  120. android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
  121. startActivityForResult(i, RESULT_LOAD_IMAGE);
  122. }
  123. });
  124. }
  125. @Override
  126. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  127. super.onActivityResult(requestCode, resultCode, data);
  128. if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK
  129. && data != null) {
  130. Uri selectedImage = data.getData();
  131. String[] filePathColumn = { MediaStore.Images.Media.DATA };
  132. Cursor cursor = getContentResolver().query(selectedImage,
  133. filePathColumn, null, null, null);
  134. cursor.moveToFirst();
  135. int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
  136. final String picturePath = cursor.getString(columnIndex);
  137. LogUtil.d(picturePath);
  138. cursor.close();
  139. imageview.setVisibility(View.VISIBLE);
  140. imageview.setImageBitmap(BitmapFactory.decodeFile(picturePath));
  141. //自定义参数returnbody
  142. //"returnBody":"{\"key\":$(key),\"hash\":$(etag),\"fname\":$(fname),\"phone\":$(x:phone)}
  143. final String token = "xxxxx";
  144. button2.setOnClickListener(new OnClickListener() {
  145. @Override
  146. public void onClick(View v) {
  147. //设定需要添加的自定义变量为Map<String, String>类型 并且放到UploadOptions第一个参数里面
  148. HashMap<String, String> map = new HashMap<String, String>();
  149. map.put("x:phone", "12345678");
  150. LogUtil.d("click upload");
  151. isCancelled = false;
  152. uploadManager.put(picturePath, null, token,
  153. new UpCompletionHandler() {
  154. public void complete(String key,
  155. ResponseInfo info, JSONObject res) {
  156. LogUtil.i(key + ",\r\n " + info
  157. + ",\r\n " + res);
  158. if(info.isOK()==true){
  159. textview.setText(res.toString());
  160. }
  161. }
  162. }, new UploadOptions(map, null, false,
  163. new UpProgressHandler() {
  164. public void progress(String key, double percent){
  165. LogUtil.i(key + ": " + percent);
  166. progressbar.setVisibility(View.VISIBLE);
  167. int progress = (int)(percent*1000);
  168. // Log.d("qiniu", progress+"");
  169. progressbar.setProgress(progress);
  170. if(progress==1000){
  171. progressbar.setVisibility(View.GONE);
  172. }
  173. }
  174. }, new UpCancellationSignal(){
  175. @Override
  176. public boolean isCancelled() {
  177. return isCancelled;
  178. }
  179. }));
  180. }
  181. });
  182. button3.setOnClickListener(new OnClickListener() {
  183. @Override
  184. public void onClick(View v) {
  185. isCancelled = true;
  186. }
  187. });
  188. }
  189. }
  190. }

上传过程进度条:
这里写图片描述
上传后自定义变量回调:
这里写图片描述

3).关于从服务器获取Token上传:
Android SDK为客户端SDK,没有包含token生成实现,为了安全,token都建议通过网络从服务端获取,具体生成代码可以参考”java/python/php/ruby/go”等服务端sdk, 其实也比较简单,可以使用okhttp发送一个简单的get请求就可以了,这里以使用SyncHttpClient为例来说明:

  1. package com.example.androidupload;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.util.Log;
  5. import android.view.Menu;
  6. import android.view.MenuItem;
  7. import com.google.gson.JsonElement;
  8. import com.google.gson.JsonParser;
  9. import com.loopj.android.http.SyncHttpClient;
  10. import com.loopj.android.http.TextHttpResponseHandler;
  11. import com.qiniu.android.storage.UpCompletionHandler;
  12. import com.qiniu.android.storage.UpProgressHandler;
  13. import com.qiniu.android.storage.UploadManager;
  14. import com.qiniu.android.storage.UploadOptions;
  15. import com.qiniu.android.utils.UrlSafeBase64;
  16. import org.apache.http.Header;
  17. import org.json.JSONObject;
  18. import java.io.File;
  19. import java.util.UUID;
  20. public class MainActivity extends Activity {
  21. private UploadManager uploadManager;
  22. private final String tag = "MainActivity";
  23. protected void onCreate(Bundle savedInstanceState) {
  24. super.onCreate(savedInstanceState);
  25. setContentView(R.layout.activity_main);
  26. //设置本地上传的文件的路径
  27. String path ="/storage/emulated/0/Download/DSC_0770.JPG";
  28. String aaa = UrlSafeBase64.encodeToString(path);
  29. File file =new File(path);
  30. }
  31. private void upload(final String localPath,final String key)
  32. {
  33. Thread thread = new Thread()
  34. {
  35. @Override
  36. public void run() {
  37. super.run();
  38. SyncHttpClient client = new SyncHttpClient();
  39. //获取服务端的token的url
  40. String url = "http://xxxx/xxxx/xxx";
  41. client.get(url, new TextHttpResponseHandler() {
  42. @Override
  43. public void onFailure(int i, Header[] headers, String s, Throwable throwable) {
  44. }
  45. @Override
  46. public void onSuccess(int i, Header[] headers, String s) {
  47. LogUtil.i("请求七牛token:"+s);
  48. JsonParser jsonParser = new JsonParser();
  49. JsonElement jsonElement =jsonParser.parse(s);
  50. String token = jsonElement.getAsJsonObject().get("uptoken").toString();
  51. LogUtil.i("七牛开始上传"+localPath+"\n"+key+"\n"+token);
  52. if(uploadManager==null)
  53. {
  54. uploadManager = new UploadManager();
  55. }
  56. UploadOptions uploadOptions = new UploadOptions(null, null, false,
  57. new UpProgressHandler() {
  58. @Override
  59. public void progress(String key, double percent) {
  60. LogUtil.i("a 七牛上传progress:"+percent+"\n"+key);
  61. }
  62. }, null);
  63. //调用uploadManager上传
  64. uploadManager.put(localPath, key, token, new UpCompletionHandler() {
  65. @Override
  66. public void complete(String key, com.qiniu.android.http.ResponseInfo info, JSONObject response) {
  67. LogUtil.i("a 七牛上传complete:"+key + ",\r\n " + info + ",\r\n " + response);
  68. }
  69. },uploadOptions);
  70. }
  71. });
  72. }
  73. };
  74. thread.start();
  75. }
  76. }

4).关于for循环上传:
可以参考demo:

  1. package com.dxy.cloud.myapplication;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.util.Log;
  5. import android.view.View;
  6. import android.widget.Button;
  7. import android.widget.TextView;
  8. import com.qiniu.android.http.ResponseInfo;
  9. import com.qiniu.android.storage.UpCompletionHandler;
  10. import com.qiniu.android.storage.UploadManager;
  11. import com.qiniu.android.storage.UploadOptions;
  12. import org.json.JSONObject;
  13. public class MainActivity extends Activity implements View.OnClickListener {
  14. //指定upToken, 强烈建议从服务端提供get请求获取, 这里为了掩饰直接指定key
  15. public static String uptoken = "xxxxxxxxx:xxxxxxx:xxxxxxxxxx";
  16. private Button btnUpload;
  17. private TextView textView;
  18. private UploadManager uploadManager;
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_main);
  23. textView = (TextView) findViewById(R.id.textView);
  24. btnUpload = (Button) findViewById(R.id.button);
  25. btnUpload.setOnClickListener(this);
  26. //new一个uploadManager类
  27. uploadManager = new UploadManager();
  28. }
  29. @Override
  30. public void onClick(View v) {
  31. LogUtil.i("starting......");
  32. byte[] data=new byte[]{ 0, 1, 2, 3, 3, 4, 5, 6,0, 1, 2, 3, 4, 5, 6,0, 1, 2, 3, 4, 5, 6,0, 1, 2, 3, 4, 5, 6,0, 1, 2, 3, 4, 5, 6,0, 1, 2, 3,};
  33. for(int i=0;i<data.length;i++){
  34. String expectKey =UUID.randomUUID().toString();
  35. uploadManager.put(data, expectKey, uptoken, new UpCompletionHandler() {
  36. public void complete(String k, ResponseInfo rinfo, JSONObject response) {
  37. String s = k + ", "+ rinfo + ", " + response;
  38. LogUtil.i(s);
  39. String key = getKey(k, response);
  40. String o = hint.getText() + "\r\n\r\n";
  41. hint.setText(o + s + "http://xm540.com1.z0.glb.clouddn.com/" + key);
  42. }
  43. }, new UploadOptions(null, "test-type", true, null, null));
  44. }
  45. }
  46. }

5).常见的返回的状态码:
使用七牛 Android sdk 的时候, 如果使用方式不正确,会返回一些对应的错误码。
具体可以参考源码:
https://github.com/qiniu/android-sdk/blob/c4cd1437aa1f2a0d68122e46b83580facdf1b74a/library/src/main/java/com/qiniu/android/http/ResponseInfo.java

  1. public static final int MaliciousResponseError = -8;
  2. public static final int LocalIOError = -7;
  3. public static final int ZeroSizeFile = -6;
  4. public static final int InvalidToken = -5;
  5. public static final int InvalidArgument = -4;
  6. public static final int InvalidFile = -3;
  7. public static final int Cancelled = -2;
  8. public static final int NetworkError = -1;
  9. public static final int TimedOut = -1001;
  10. public static final int UnknownHost = -1003;
  11. public static final int CannotConnectToHost = -1004;
  12. public static final int NetworkConnectionLost = -1005;

6).关于混淆配置:

混淆处理 对七牛的SDK不需要做特殊混淆处理,混淆时将七牛相关的包都排除就可以了。

在Android Studio中,混淆配置在 proguard-rules.pro 里面加上下面几行混淆代码就行:

  1. -keep class com.qiniu.**{*;}
  2. -keep class com.qiniu.**{public <init>();}
  3. -ignorewarnings

注意:-ignorewarnings这个也是必须加的,如果不加这个编译的时候可能是可以通过的,但是release的时候还是会出现错误。

对于Eeclipse中也是一样的,在proguard-project.txt 文件附件同样的排除代码就可以了

  1. -keep class com.qiniu.**{*;}
  2. -keep class com.qiniu.**{public <init>();}
  3. -ignorewarnings

7).为什么进度会在95% 停很久:
因为上传进度是用sdk写入socket的 字节数/总字节数 作为进度,但写入socket不等于服务器收到并且处理完成,中间还有一段时间,如果只是用字节数就会出现更怪异的情况,在100% 停留很久,所以综合考虑就使用了 95%这个值.

8).如何对文件名字做模糊查询:
如果前缀查询满足不了需求,想做多维度的查询,比如日期,userid, 文件名中的字段进行查询,可以通过开通Pandora 日志查询服务来满足。下面的例子里面需要在工作流上创建key, user, etag, mime, 四个字段的repo, 具体客户端做法如下,在上传结束后,再把结果打点到pandora 服务

  1. import com.qiniu.android.storage.UploadManager;
  2. import com.qiniu.android.bigdata.pipeline.Pipeline;
  3. ...
  4. String token = "从服务端SDK获取";
  5. UploadManager uploadManager = new UploadManager();
  6. String pipelineToken = "从服务端获取 或者 生成一个长时间的token";
  7. Pipeline pipe = new Pipeline();
  8. uploadManager.put("Hello, World!".getBytes(), "hello", token,
  9. new UpCompletionHandler() {
  10. @Override
  11. public void complete(String key, ResponseInfo info, JSONObject response) {
  12. Map<String, Object> inf = new HashMap<String, Object>();
  13. inf.put("key", key);
  14. inf.put("user", "userid");
  15. inf.put("etag", resp.getString("hash"));
  16. inf.put("mime", resp.getString("mimeType"));
  17. pipe.pump("keysearchRepo", inf, pipelineToken, new Pipeline.PumpCompleteHandler() {
  18. @Override
  19. public void complete(ResponseInfo inf2) {
  20. ...
  21. }
  22. });
  23. }
  24. }, null);
  25. ...

9).如何理解上传返回 code :
详情 code 注释说明

代码贡献

详情参考代码提交指南

贡献记录

联系我们

  • 如果需要帮助,请提交工单(在portal右侧点击咨询和建议提交工单,或者直接向 support@qiniu.com 发送邮件)
  • 如果有什么问题,可以到问答社区提问,问答社区
  • 更详细的文档,见官方文档站
  • 如果发现了bug, 欢迎提交 issue
  • 如果有功能需求,欢迎提交 issue
  • 如果要提交代码,欢迎提交 pull request
  • 欢迎关注我们的微信 微博,及时获取动态信息。

代码许可

The MIT License (MIT).详情见 License文件.