1

这是我的第一个 Android 应用程序,所以请放轻松。这个想法是检测用户何时将照片放入 /mnt/sdcard 并将其上传到 Imgur,然后将链接复制到系统剪贴板。

正在使用的类

我的应用程序中有三个课程。ObserveNewImages用于FileObserver检测前述路径中的新照片。

观察图像.java

public class ObserveNewImages extends Service {

final String pathToObserve = android.os.Environment.getExternalStorageDirectory().toString(); // stores "/mnt/sdcard"
final String upload_to = "https://api.imgur.com/3/upload.json";
final String API_key = "API_KEY_GOES_HERE";
public static final String TAG = "Awais";


String link; //full path to where the image is stored
Intent upload;


@Override
public void onCreate(){
    upload = new Intent(this, Imgur.class); //just initializing an intent for use later. Nothing special.
    super.onCreate();
}



@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "In onStartCommand");
    FileObserver observer = new FileObserver(pathToObserve){
        //As soon as we detect a new file in pathToObserve
            //, I fire up the service for uploading image to Imgur.

        @Override
        public void onEvent(int event, String file){
            if (event == FileObserver.CREATE){
                Log.d(TAG, "file address: " + pathToObserve + "/" + file);
                link = pathToObserve + "/" + file;
                upload.putExtra("path",link);
                startService(upload);
            }

        }
    };

    observer.startWatching();

    return super.onStartCommand(intent, flags, startId);
}

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}
}

继续Imgur.java其中包括两个类Imgur.class和一个ImgurTask扩展类,AsyncTask以便网络任务在单独的线程上进行。

Imgur.java

public class Imgur extends Service{

String path;

@Override
public void onCreate() {
    // TODO Auto-generated method stub
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    path = intent.getStringExtra("path");
    new ImgurTask().execute(path); 

    return super.onStartCommand(intent, flags, startId);
}

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}

class ImgurTask extends AsyncTask<String, Void, String>{


    final String upload_to = "https://api.imgur.com/3/upload.json";
    final String API_key = "API_KEY_GOES_HERE";
    public static final String TAG = "Awais";
    String link;


    @Override
    protected String doInBackground(String... params) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        HttpPost httpPost = new HttpPost(upload_to);
        httpPost.setHeader("Authorization", "Client-ID " + API_key);        


        try {
            MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

            entity.addPart("image", new FileBody(new File(params[0])));
            entity.addPart("key", new StringBody(API_key));

            httpPost.setEntity(entity);

            HttpResponse response = httpClient.execute(httpPost, localContext);

            String response_string = EntityUtils.toString(response.getEntity());
            Log.d(TAG, "Response from Imgur: " + response_string);
            JSONObject json = new JSONObject(response_string);

            //Parsing JSON manually since I couldn't get it work using JSONObject's built-in class functions
            String json_str = json.toString();
            Integer indexlink = json_str.indexOf("link");

            Integer colonlink = json_str.indexOf(":", indexlink);
            Integer secondbracket = json_str.indexOf("}", colonlink);
            link = json_str.substring(colonlink+2, secondbracket-1);

            link = link.replace("\\","");

            return link;

        }catch (Exception e){
            e.printStackTrace();
        }
        return "error";
    }

    @Override
    protected void onPostExecute(String result) {
        if (result != "error"){
                            //copying link to clipboard
            ClipboardManager clipboard = (ClipboardManager)getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE); 
            ClipData clip = ClipData.newPlainText("Imgur link", result);
            clipboard.setPrimaryClip(clip);
            Toast.makeText(getApplicationContext(), "Link is ready to paste: " + result, Toast.LENGTH_SHORT).show();

        }
        else{
            Toast.makeText(getApplicationContext(), "Error: Are you connected to the Internet?", Toast.LENGTH_SHORT).show();
        }
        super.onPostExecute(result);
    }
}
}

MainActivity.java

这仅用于启动ObserveImages服务。

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //start service
    Intent start_observing = new Intent(this, ObserveImages.class);
    startService(start_observing);
    Toast.makeText(getApplicationContext(), "Automatic Image Uploader is now running!", Toast.LENGTH_SHORT).show();
    finish();
}

}

问题

存在三个问题:

  • 服务只是在一段时间后停止工作。没有任何内容显示日志(我已从此处的代码中删除)以表明应用程序正在运行。为了让事情再次运行,我必须再次从应用程序图标启动。

  • 在几次上传(有时是 4-5 次,有时最多 10 次)之后,Imgur 的服务器会发送一个 405 Not Allowed 响应。离开应用程序一分钟,然后再回来,服务器会发回正确的响应。

  • 应用程序在一段时间后崩溃。FileObserver 类引发空指针异常。

4

1 回答 1

0

根据超时问题,它内置在 API 中。

  • access_token:是您用于访问用户数据的密钥。可以认为用户的密码和用户名合二为一,用于访问用户的账户。它会在 1 小时后过期。

不过我不知道另外两个是怎么回事。您能否分享 FileObserver 问题的错误堆栈?它可能会有所帮助。

自动上传到 Imgur 是一个非常好的主意。但是不要忘记速率限制(每天上传 1,250 次或每天大约 12,500 次请求)。甚至可能包括一些处理,当他们开始接近一个或另一个限制时,可能会通知用户(尽管我真的不知道任何人怎么能做到,因为他们非常慷慨)。

于 2013-05-31T19:45:50.770 回答