افزودن دراپ باکس به اپلیکیشن اندروید

افزودن دراپ باکس به اپلیکیشن اندروید

ذخیره سازی داکیومنت و فایل نقش بسزایی در دستگاه های محاسباتی دارد. ذخیره سازی به سبک سنتی به صورت لوکال انجام می شود، اما با روی کار آمدن سیستم های ابری مکان ذخیره سازی مستندات نیز تغییر یافته است. ذخیره سازی کلود نیز دارای مشکلات منحصر به فرد خود می باشد، اما با در نظر گرفتن ظرفیت نامحدود و هزینه کم آن می توان بسیاری از مشکلات را نادیده گرفت.

در این مطلب آموزشی نحوه ذخیره سازی فایل ها از یک اپلیکیشن اندروید در دراپ باکس با استفاده از SDK اصلی دراپ باکس برای نسخه های 6 و بالاتر از جاوا در اندروید شرح داده خواهد شد. مبنی بر توضیحات، این Core SDK یک کتابخانه جاواست که به نسخه 2 از API مبتنی بر HTTP دسترسی دارد. این SDK از نسخه های قدیمی تر Core API v1 نیز پشتیبانی می کند، اما این پشتیبانی در آینده حذف خواهد شد. کد نهایی این پروژه را می توانید از GitHub دانلود کرده و مورد استفاده قرار دهید.

برای متصل شدن به دراپ باکس باید یک اکانت دراپ باکس بسازید و API دراپ باکس را مورد استفاده قرار دهید. یک اپلیکیشن جدید در App Console بسازید.

blog_19353_1

پس از اینکه اپلیکیشن جدید ساخته شد به وضعیت توسعه در می آید، اپلیکیشن در این شرایط تنها قابل استفاده توسط کاربران تستی است و چنانچه شما Additional Users را فعال کنید، 100 کاربر پپشتیبانی می شوند. زمانی که کار توسعه و ساخت اپلیکیشن تکمیل شد می توانید وضعیت را به تولید تغییر دهید.

کنسول اپلیکیشن دربرگیرنده اطلاعات اپلیکیشن است و شما به App Key نیز برای پروژه اندروید نیاز خواهید داشت.

bog_19353_2

افزودن مجوزهای دسترسی

با استفاده از Login Activity یک پروژه در اندروید استودیو بسازید و در فایل AndroidManifest.xml کدهای زیر را برای مجوزهای اینترنت و ذخیره سازی بیفزایید. می توانید مجوزهای پیش فرض تولید شده در فایل که توسط LoginActivity تولید شده است را نیز پاک کنید.

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

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

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

افزودن وابستگی ها

در فایل build.gradle کدهای زیر را اضافه کنید:

dependencies {

//...

compile 'com.dropbox.core:dropbox-core-sdk:2.0.1'

compile 'com.squareup.picasso:picasso:2.5.2'

}

نکته: وابستگی اول برای Core API دراپ باکس می باشد، استفاده از کتابخانه Picasso اجباری نیست، اما برای لود کردن تصاویر کاربردی می باشد.

افزودن اکتیویتی دراپ باکس

فایل AndroidManifest.xml را باز کنید و در قسمت <application></application> اکتیویتی AuthActivity را بیفزایید.

<application>

...

<!-- Dropbox AuthActivity -->

<activity

android:name="com.dropbox.core.android.AuthActivity"

android:configChanges="orientation|keyboard"

android:launchMode="singleTask">

<intent-filter>

<!-- Insert your app key after “db- ...” -->

<data android:scheme="db-APP_KEY" />

<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.BROWSABLE" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

</application>

خطای فایل تکراری

در حین تست اپلیکیشن ممکن است با خطایی مبنی بر تداخل در زمان بیلد چندین فایل License.txt یا Notice.txt مواجه شوید، به منظور پیشگیری از این مشکل در فایل build.gradle در بخش {…}android این فایل ها را خارج کنید.

android {

...

packagingOptions {

exclude 'META-INF/LICENSE'

exclude 'META-INF/LICENSE.txt'

exclude 'META-INF/NOTICE'

exclude 'META-INF/NOTICE.txt'

}

}

کلید اپلیکیشن

app key را به فایل strings.xml بیفزایید.

<!-- Change this to your app key -->

<string name="APP_KEY">APP_KEY_HERE</string>

در این مرحله پروژه اندروید برای استفاده از API دراپ باکس پیکربندی شده است، حال باید یک اکتیویتی جدید را به پروژه بیفزایید، این کار با استفاده از آیتم منوی File->New->Activity->Basic Activity انجام می شود، نام آن را MainActivity.java بگذارید.

توضیحات پروژه

این اپلیکیشن نمونه به اکانت دراپ باکس کاربر وارد شده، اطلاعات جزئی را دریافت می کند و یک عکس را به فولدر دراپ باکس اپلیکیشن آپلود می کند. این پروژه دو اکتیویتی به نام های LoginActivity و MainActivity خواهد داشت.

ورود با استفاده از دراپ باکس

وظیفه LoginActivity بسیار ساده و روشن است، با کلیک بر روی دکمه این اکتیویتی عملیات ورود به سیستم را به اجرا در آورده و یک توکن دسترسی را برای اپلیکیشن دراپ باکس تولید می کند که در منابع رشته ها با نام APP_KEY شناخته می شود.

متد ()startOAuthentication یک اکتیویتی AuthActivity را که به فایل Manifest افزوده شده بود باز می کند. در AuthActivity کاربر باید اکانت دراپ باکس خود را تایید کند، پس از این کار کاربر به loginActivity ری دایرکت می شود.

متد ()StartOAuthentication هیچ توکن دسترسی را بر نمی گرداند، این متد تنها AuthActivity را باز می کند که برای احراز هویت کاربر استفاده می شود. هم اکنون که کاربر احراز هویت شد، به یک توکن دسترسی نیاز دارد.

AuthActivity

blog_19353_3

در LoginActivity کدهای تولیدشده خودکار به جز نام پکیج پروژه را با کدهای زیر جایگزین کنید:

public class LoginActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

Button SignInButton = (Button) findViewById(R.id.sign_in_button);

SignInButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View view) {

Auth.startOAuth2Authentication(getApplicationContext(), getString(R.string.APP_KEY));

}

});

}

@Override

protected void onResume() {

super.onResume();

getAccessToken();

}

public void getAccessToken() {

String accessToken = Auth.getOAuth2Token(); //generate Access Token

if (accessToken != null) {

//Store accessToken in SharedPreferences

SharedPreferences prefs = getSharedPreferences("com.example.valdio.dropboxintegration", Context.MODE_PRIVATE);

prefs.edit().putString("access-token", accessToken).apply();

//Proceed to MainActivity

Intent intent = new Intent(LoginActivity.this, MainActivity.class);

startActivity(intent);

}

}

}

برای لی اوت این اکتیویتی فایل activity_login.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"

tools:context="com.example.valdio.dropboxintegration.LoginActivity">

<!-- Update package name -->

<Button

android:id="@+id/sign_in_button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/sign_in"

android:layout_centerVertical="true"

android:layout_centerHorizontal="true" />

</RelativeLayout>

کدهای زیر را برای sign in در متن دکمه به فایل strings.xml اضافه کنید:

...

<string name="sign_in">Sign in</string>

متد ()onResume از LoginActivity با فراخوانی متد ()GetOAuth2Token توکن موردنظر را درخواست می کند. این توکن برای کاربرد آینده در داده های SharedPreferences ذخیره شده و سپس MainActivity باز می شود.

متد ()onResume پیش از آنکه اپلیکیشن برای اولین بار باز شود فراخوانی می شود، اما چرا پس از آن توکن را دریافت نمی کنید؟

دلیل این شرایط این است که قبل از ورود به سیستم کاربر هنوز احراز هویت نشده و توکنی تولید نشده است، در صورت احراز هویت موفقیت آمیز پس از AuthActivity، متد ()onResume یک بار دیگر فراخوانی شده و توکن موردنظر را تولید خواهد نمود.

کلاینت دراپ باکس هم اکنون وارد شده است

در MainAvtivity متغییرهای زیر را تعریف کنید:

public class MainActivity extends AppCompatActivity {

private static final int IMAGE_REQUEST_CODE = 101;

private String ACCESS_TOKEN;

...

}

در فایل لی اوت content_main.xml از MainActivity محتوا را با کدهای زیر جایگزین کنید:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="@dimen/activity_vertical_margin"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

app:layout_behavior="@string/appbar_scrolling_view_behavior"

tools:context="valdioveliu.valdio.com.dropboxintegration.MainActivity"

tools:showIn="@layout/activity_main">

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical"

android:id="@+id/accountData">

<ImageView

android:id="@+id/imageView"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentTop="true"

android:layout_centerHorizontal="true" />

<TextView

android:id="@+id/textView3"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentStart="true"

android:layout_below="@+id/imageView"

android:layout_marginLeft="15dp"

android:layout_marginTop="50dp"

android:text="Name"

android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView

android:id="@+id/name_textView"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentStart="true"

android:gravity="center_horizontal"

android:text=""

android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView

android:id="@+id/textView"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentStart="true"

android:layout_below="@+id/textView3"

android:layout_marginLeft="15dp"

android:layout_marginTop="58dp"

android:text="Email"

android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView

android:id="@+id/email_textView"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentStart="true"

android:layout_below="@+id/textView"

android:gravity="center_horizontal"

android:text=""

android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

</RelativeLayout>

اطلاعات اکانت

دریافت اطلاعات کاربر یا دسترسی به دراپ باکس از هر طریقی یک درخواست شبکه است و در اندروید این قبیل از درخواست ها به صورت ناهمگام ترتیب اثر داده می شوند. این درخواست های شبکه همگی به یک کلاینت دراپ باکس نیاز دارند.

یک DropboxClient.java ساخته و کد زیر را به آن اضافه کنید:

ublic class DropboxClient {

public static DbxClientV2 getClient(String ACCESS_TOKEN) {

// Create Dropbox client

DbxRequestConfig config = new DbxRequestConfig("dropbox/sample-app", "en_US");

DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN);

return client;

}

}

رشته ACCESS_TOKEN در متد ()getClinet همان توکنی است که در زمان وارد شدن کاربر دریافت شده است.

کار بعدی دریافت اطلاعات اکانت کاربر می باشد، کلاس UserAccountTask نمایش دهنده درخواست اطلاعات کاربر می باشد. سازنده این کلاس غیرهمزمان دارای یک پارامتر رابط از TaskDelegate است که برای برگرداندن اطلاعات اکانت به اکتیویتی که این وظیفه در آن اجرا شده، مورد استفاده قرار گرفته است.

فایل UserAccountTask.java را ساخته و کدهای زیر را به آن اضافه کنید:

public class UserAccountTask extends AsyncTask<Void, Void, FullAccount>  {

private DbxClientV2 dbxClient;

private TaskDelegate delegate;

private Exception error;

public interface TaskDelegate {

void onAccountReceived(FullAccount account);

void onError(Exception error);

}

UserAccountTask(DbxClientV2 dbxClient, TaskDelegate delegate){

this.dbxClient =dbxClient;

this.delegate = delegate;

}

@Override

protected FullAccount doInBackground(Void... params) {

try {

//get the users FullAccount

return dbxClient.users().getCurrentAccount();

} catch (DbxException e) {

e.printStackTrace();

error = e;

}

return null;

}

@Override

protected void onPostExecute(FullAccount account) {

super.onPostExecute(account);

if (account != null && error == null){

//User Account received successfully

delegate.onAccountReceived(account);

}

else {

// Something went wrong

delegate.onError(error);

}

}

}

متد getUserAccount مثالی از نحوه اجرای کلاس UserAccountTask در کلاس MainActivity می باشد.

متد زیر را که در ادامه مورد استفاده قرار خواهد گرفت، به کلاس MainActivity بیفزایید:

protected void getUserAccount() {

if (ACCESS_TOKEN == null)return;

new UserAccountTask(DropboxClient.getClient(ACCESS_TOKEN), new UserAccountTask.TaskDelegate() {

@Override

public void onAccountReceived(FullAccount account) {

//Print account's info

Log.d("User", account.getEmail());

Log.d("User", account.getName().getDisplayName());

Log.d("User", account.getAccountType().name());

updateUI(account);

}

@Override

public void onError(Exception error) {

Log.d("User", "Error receiving account details.");

}

}).execute();

}

به منظور نمایش اطلاعات اکانت کاربر در رابط کاربری تابع زیر را به کلاس MainActivity اضافه کنید:

private void updateUI(FullAccount account) {

ImageView profile = (ImageView) findViewById(R.id.imageView);

TextView name = (TextView) findViewById(R.id.name_textView);

TextView email = (TextView) findViewById(R.id.email_textView);

name.setText(account.getName().getDisplayName());

email.setText(account.getEmail());

Picasso.with(this)

.load(account.getProfilePhotoUrl())

.resize(200, 200)

.into(profile);

}

آپلود در دراپ باکس

وظایف آپلود با کمک InputStream صورت می پذیرند، بدین ترتیب که فایل مشخص شده با کمک Core SDK به یک InputStream تبدیل می شود و استریم به فولدر اپلیکیشن ها در دراپ باکس آپلود می شود.

فایل UploadTask.java را ساخته و کد زیر را به آن بیفزایید:

public class UploadTask extends AsyncTask {

private DbxClientV2 dbxClient;

private File file;

private Context context;

UploadTask(DbxClientV2 dbxClient, File file, Context context) {

this.dbxClient = dbxClient;

this.file = file;

this.context = context;

}

@Override

protected Object doInBackground(Object[] params) {

try {

// Upload to Dropbox

InputStream inputStream = new FileInputStream(file);

dbxClient.files().uploadBuilder("/" + file.getName()) //Path in the user's Dropbox to save the file.

.withMode(WriteMode.OVERWRITE) //always overwrite existing file

.uploadAndFinish(inputStream);

Log.d("Upload Status", "Success");

} catch (DbxException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

@Override

protected void onPostExecute(Object o) {

super.onPostExecute(o);

Toast.makeText(context, "Image uploaded successfully", Toast.LENGTH_SHORT).show();

}

}

نکته: اندروید استودیو پیام هشداری مبنی بر تداخل ورودی ها نشان می دهد که لازم است با وارد کردن java.io.file برای متغییر file این مشکل را برطرف نمایید.

به منظور انجام یک آپلود اول از همه به یک فایل مانند عکس نیاز دارید، می توانید با شروع یک اکتیویتی دیگر تصویر را دریافت کنید.

متد زیر را به MainActivity بیفزایید:

private void upload() {

if (ACCESS_TOKEN == null)return;

//Select image to upload

Intent intent = new Intent();

intent.setType("image/*");

intent.setAction(Intent.ACTION_GET_CONTENT);

intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);

startActivityForResult(Intent.createChooser(intent,

"Upload to Dropbox"), IMAGE_REQUEST_CODE);

}

در هنگام فراخوانی ()startActivityForResult نیاز به جایگذاری متد ()onActivityResult برای مدیریت نتایج در MainActivity دارید. زمانی که یک URI عکس معتبر دریافت شد، یک فایل ساخته و UploudTask را به اجرا در آورید.

متد زیر را به MainActivity بیفزایید:

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

if (resultCode != RESULT_OK || data == null) return;

// Check which request we're responding to

if (requestCode == IMAGE_REQUEST_CODE) {

// Make sure the request was successful

if (resultCode == RESULT_OK) {

//Image URI received

File file = new File(URI_to_Path.getPath(getApplication(), data.getData()));

if (file != null) {

//Initialize UploadTask

new UploadTask(DropboxClient.getClient(ACCESS_TOKEN), file, getApplicationContext()).execute();

}

}

}

}

در متد ()onActivityResult پارامتر(()URI_to_Path.getPath(getApplication(), data.getData وجود دارد. کلاس جاوای URI_to_Path یک کلاس کمک کننده برای تبدیل URI به مسیرهای مطلق می باشد و یک کلاس بزرگ است و در این مطلب آموزشی به آن پرداخته نمی شود، بنابراین یک کلاس URI_to_Path.java ساخته و این کد را به آن اضافه کنید و نام پکیج را هم مطابق با پروژه خود تغییر دهید.

بالاخره نوبت به متد ()onCreate می رسد، کد زیر را به MainActivity افزوده و هرچیزی که در حال حاضر در آن وجود دارد را پاک کنید:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

setSupportActionBar(toolbar);

if (!tokenExists()) {

//No token

//Back to LoginActivity

Intent intent = new Intent(MainActivity.this, LoginActivity.class);

startActivity(intent);

}

ACCESS_TOKEN = retrieveAccessToken();

getUserAccount();

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);

fab.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

upload();

}

});

}

هر بار با باز شده اپلیکیشن لازم است تا وجود توکن دسترسی را چک کنید، چنانچه توکن وجود داشته باشد، آن را از SharedPreferences بازیابی کنید و متدهای زیر را برای انجام این کار به MainActivity اضافه نمایید.

private boolean tokenExists() {

SharedPreferences prefs = getSharedPreferences("com.example.valdio.dropboxintegration", Context.MODE_PRIVATE);

String accessToken = prefs.getString("access-token", null);

return accessToken != null;

}

private String retrieveAccessToken() {

//check if ACCESS_TOKEN is stored on previous app launches

SharedPreferences prefs = getSharedPreferences("com.example.valdio.dropboxintegration", Context.MODE_PRIVATE);

String accessToken = prefs.getString("access-token", null);

if (accessToken == null) {

Log.d("AccessToken Status", "No token found");

return null;

} else {

//accessToken already exists

Log.d("AccessToken Status", "Token exists");

return accessToken;

}

}

نتیجه گیری

در این مطلب مقدماتی از یکپارچه سازی دراپ باکس با نسخه 2 از API در اندروید را فرا گرفتید، در صورت تمایل به دریافت جزئیات بیشتر درباره این موضوع می توانید به مستندات دراپ باکس برای جاوا، منبع SDK و مثال ها نگاهی بیندازید.

 

https://www.sitepoint.com برگرفته از

اینها را هم بخوانید