studio - rest api android что это




Служба Restful API (8)

Я хочу сделать сервис, который я могу использовать для звонков в веб-REST API.

В принципе, я хочу запустить службу в приложении init, тогда я хочу попросить эту службу запросить URL-адрес и вернуть результаты. Тем временем я хочу иметь возможность отображать окно прогресса или что-то подобное.

Я создал службу в настоящее время, которая использует IDL, я где-то читал, что вам действительно нужно это только для общения по перекрестным приложениям, поэтому подумайте, что эти потребности устраняются, но не уверены, как делать обратные вызовы без него. Также, когда я попал в post(Config.getURL("login"), values) приложение, кажется, некоторое время приостанавливается (кажется странным - мысль о том, что служба была в том, что она работает в другом потоке!)

В настоящее время у меня есть служба с сообщением и методы http внутри, несколько файлов AIDL (для двусторонней связи), ServiceManager, который занимается запуском, остановкой, привязкой и т. Д. К службе, и я динамически создаю обработчик с определенным кодом для обратных вызовов по мере необходимости.

Я не хочу, чтобы кто-нибудь дал мне полную базу кода, над которой можно было бы работать, но некоторые указатели будут очень благодарны.

Код в (в основном) полный:

public class RestfulAPIService extends Service  {

final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>();

public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
}
public IBinder onBind(Intent intent) {
    return binder;
}
public void onCreate() {
    super.onCreate();
}
public void onDestroy() {
    super.onDestroy();
    mCallbacks.kill();
}
private final IRestfulService.Stub binder = new IRestfulService.Stub() {
    public void doLogin(String username, String password) {

        Message msg = new Message();
        Bundle data = new Bundle();
        HashMap<String, String> values = new HashMap<String, String>();
        values.put("username", username);
        values.put("password", password);
        String result = post(Config.getURL("login"), values);
        data.putString("response", result);
        msg.setData(data);
        msg.what = Config.ACTION_LOGIN;
        mHandler.sendMessage(msg);
    }

    public void registerCallback(IRemoteServiceCallback cb) {
        if (cb != null)
            mCallbacks.register(cb);
    }
};

private final Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {

        // Broadcast to all clients the new value.
        final int N = mCallbacks.beginBroadcast();
        for (int i = 0; i < N; i++) {
            try {
                switch (msg.what) {
                case Config.ACTION_LOGIN:
                    mCallbacks.getBroadcastItem(i).userLogIn( msg.getData().getString("response"));
                    break;
                default:
                    super.handleMessage(msg);
                    return;

                }
            } catch (RemoteException e) {
            }
        }
        mCallbacks.finishBroadcast();
    }
    public String post(String url, HashMap<String, String> namePairs) {...}
    public String get(String url) {...}
};

Несколько файлов AIDL:

package com.something.android

oneway interface IRemoteServiceCallback {
    void userLogIn(String result);
}

а также

package com.something.android
import com.something.android.IRemoteServiceCallback;

interface IRestfulService {
    void doLogin(in String username, in String password);
    void registerCallback(IRemoteServiceCallback cb);
}

и сервис-менеджер:

public class ServiceManager {

    final RemoteCallbackList<IRemoteServiceCallback> mCallbacks = new RemoteCallbackList<IRemoteServiceCallback>();
    public IRestfulService restfulService;
    private RestfulServiceConnection conn;
    private boolean started = false;
    private Context context;

    public ServiceManager(Context context) {
        this.context = context;
    }

    public void startService() {
        if (started) {
            Toast.makeText(context, "Service already started", Toast.LENGTH_SHORT).show();
        } else {
            Intent i = new Intent();
            i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
            context.startService(i);
            started = true;
        }
    }

    public void stopService() {
        if (!started) {
            Toast.makeText(context, "Service not yet started", Toast.LENGTH_SHORT).show();
        } else {
            Intent i = new Intent();
            i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
            context.stopService(i);
            started = false;
        }
    }

    public void bindService() {
        if (conn == null) {
            conn = new RestfulServiceConnection();
            Intent i = new Intent();
            i.setClassName("com.something.android", "com.something.android.RestfulAPIService");
            context.bindService(i, conn, Context.BIND_AUTO_CREATE);
        } else {
            Toast.makeText(context, "Cannot bind - service already bound", Toast.LENGTH_SHORT).show();
        }
    }

    protected void destroy() {
        releaseService();
    }

    private void releaseService() {
        if (conn != null) {
            context.unbindService(conn);
            conn = null;
            Log.d(LOG_TAG, "unbindService()");
        } else {
            Toast.makeText(context, "Cannot unbind - service not bound", Toast.LENGTH_SHORT).show();
        }
    }

    class RestfulServiceConnection implements ServiceConnection {
        public void onServiceConnected(ComponentName className, IBinder boundService) {
            restfulService = IRestfulService.Stub.asInterface((IBinder) boundService);
            try {
            restfulService.registerCallback(mCallback);
            } catch (RemoteException e) {}
        }

        public void onServiceDisconnected(ComponentName className) {
            restfulService = null;
        }
    };

    private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
        public void userLogIn(String result) throws RemoteException {
            mHandler.sendMessage(mHandler.obtainMessage(Config.ACTION_LOGIN, result));

        }
    };

    private Handler mHandler;

    public void setHandler(Handler handler) {
        mHandler = handler;
    }
}

Сервис init и bind:

// this I'm calling on app onCreate
servicemanager = new ServiceManager(this);
servicemanager.startService();
servicemanager.bindService();
application = (ApplicationState)this.getApplication();
application.setServiceManager(servicemanager);

вызов служебной функции:

// this lot i'm calling as required - in this example for login
progressDialog = new ProgressDialog(Login.this);
progressDialog.setMessage("Logging you in...");
progressDialog.show();

application = (ApplicationState) getApplication();
servicemanager = application.getServiceManager();
servicemanager.setHandler(mHandler);

try {
    servicemanager.restfulService.doLogin(args[0], args[1]);
} catch (RemoteException e) {
    e.printStackTrace();
}

...later in the same file...

Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {

        switch (msg.what) {
        case Config.ACTION_LOGIN:

            if (progressDialog.isShowing()) {
                progressDialog.dismiss();
            }

            try {
                ...process login results...
                }
            } catch (JSONException e) {
                Log.e("JSON", "There was an error parsing the JSON", e);
            }
            break;
        default:
            super.handleMessage(msg);
        }

    }

};

Также, когда я попал в сообщение (Config.getURL («login»), значения), приложение, кажется, некоторое время приостанавливается (кажется странным - мысль о том, что служба была в том, что она работает в другом потоке!)

В этом случае лучше использовать asynctask, которая работает в другом потоке и возвращает результат обратно в поток ui при завершении.


Также, когда я попал в сообщение (Config.getURL («login»), значения), приложение, кажется, некоторое время приостанавливается (кажется странным - мысль о том, что служба была в том, что она работает в другом потоке!)

Нет, вам нужно создать поток самостоятельно, по умолчанию работает локальная служба в потоке пользовательского интерфейса.


Если ваша служба будет частью вашего приложения, вы сделаете ее более сложной, чем она должна быть. Поскольку у вас есть простой пример получения некоторых данных из веб-службы RESTful, вы должны изучить ResultReceiver и IntentService .

Этот шаблон Service + ResultReceiver работает путем запуска или привязки к службе с помощью startService() когда вы хотите выполнить какое-либо действие. Вы можете указать операцию для выполнения и передачи в ResultReceiver (активность) через дополнительные функции в Intent.

В службе вы реализуете onHandleIntent чтобы выполнить операцию, указанную в намерении. Когда операция завершена, вы используете переданный в ResultReceiver, чтобы send сообщение обратно в Activity, в который будет вызываться onReceiveResult .

Например, вы хотите извлечь некоторые данные из своей веб-службы.

  1. Вы создаете намерение и вызываете startService.
  2. Операция в службе начинается, и она отправляет в действие сообщение с сообщением об этом
  3. Активность обрабатывает сообщение и показывает прогресс.
  4. Служба завершает операцию и отправляет некоторые данные обратно в вашу деятельность.
  5. Ваша деятельность обрабатывает данные и помещается в виде списка
  6. Служба отправляет вам сообщение о том, что оно сделано, и оно убивает себя.
  7. Действие получает сообщение завершения и скрывает диалог выполнения.

Я знаю, что вы упомянули, что вам не нужна база кода, но приложение с открытым исходным кодом Google I / O 2010 использует службу таким образом, что я описываю.

Обновлен, чтобы добавить пример кода:

Активность.

public class HomeActivity extends Activity implements MyResultReceiver.Receiver {

    public MyResultReceiver mReceiver;

    public void onCreate(Bundle savedInstanceState) {
        mReceiver = new MyResultReceiver(new Handler());
        mReceiver.setReceiver(this);
        ...
        final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, QueryService.class);
        intent.putExtra("receiver", mReceiver);
        intent.putExtra("command", "query");
        startService(intent);
    }

    public void onPause() {
        mReceiver.setReceiver(null); // clear receiver so no leaks.
    }

    public void onReceiveResult(int resultCode, Bundle resultData) {
        switch (resultCode) {
        case RUNNING:
            //show progress
            break;
        case FINISHED:
            List results = resultData.getParcelableList("results");
            // do something interesting
            // hide progress
            break;
        case ERROR:
            // handle the error;
            break;
    }
}

Сервис:

public class QueryService extends IntentService {
    protected void onHandleIntent(Intent intent) {
        final ResultReceiver receiver = intent.getParcelableExtra("receiver");
        String command = intent.getStringExtra("command");
        Bundle b = new Bundle();
        if(command.equals("query") {
            receiver.send(STATUS_RUNNING, Bundle.EMPTY);
            try {
                // get some data or something           
                b.putParcelableArrayList("results", results);
                receiver.send(STATUS_FINISHED, b)
            } catch(Exception e) {
                b.putString(Intent.EXTRA_TEXT, e.toString());
                receiver.send(STATUS_ERROR, b);
            }    
        }
    }
}

Расширение ResultReceiver - изменено для реализации MyResultReceiver.Receiver

public class MyResultReceiver implements ResultReceiver {
    private Receiver mReceiver;

    public MyResultReceiver(Handler handler) {
        super(handler);
    }

    public void setReceiver(Receiver receiver) {
        mReceiver = receiver;
    }

    public interface Receiver {
        public void onReceiveResult(int resultCode, Bundle resultData);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        if (mReceiver != null) {
            mReceiver.onReceiveResult(resultCode, resultData);
        }
    }
}

Здесь есть и другой подход, который в основном помогает забыть обо всем управлении запросами. Он основан на методе асинхронной очереди и ответе на вызов / обратный вызов. Главное преимущество заключается в том, что с помощью этого метода вы сможете полностью обработать весь процесс (запрос, получить и проанализировать ответ, sabe to db), полностью прозрачный для вас. Как только вы получите код ответа, работа уже выполнена. После этого вам просто нужно позвонить в свой db, и все готово. Это также помогает с проблемой того, что происходит, когда ваша активность не активна. Что будет здесь, так это то, что все ваши данные будут сохранены в локальной базе данных, но ответ не будет обработан вашей деятельностью, это идеальный способ.

Я написал об общем подходе здесь http://ugiagonzalez.com/2012/07/02/theres-life-after-asynctasks-in-android/

Я буду размещать конкретный пример кода в предстоящих сообщениях. Надеюсь, что это поможет, не стесняйтесь обращаться ко мне за то, чтобы поделиться этим подходом и решить потенциальные сомнения или проблемы.


Просто хотел указать всех вас в сторону отдельного класса, который я прокатил, который включает в себя все функциональные возможности.

http://github.com/StlTenny/RestService

Он выполняет запрос как неблокирующий и возвращает результаты в легко реализуемом обработчике. Даже поставляется с примером реализации.


Робби дает отличный ответ, хотя я вижу, что вы все еще ищете дополнительную информацию. Я реализовал REST api - это просто, но не так. Только после просмотра этого видео ввода-вывода Google я понял, где я ошибся. Это не так просто, как собрать AsyncTask с вызовом get / put HttpUrlConnection.


Я знаю, что @Martyn не хочет полного кода, но я думаю, что это аннотирование полезно для этого вопроса:

10 Android-приложений с открытым исходным кодом, которые каждый разработчик Android должен изучить

Foursquared для Android является open-source и имеет интересный шаблон кода, взаимодействующий с API RESTsquare.


Разработка клиентских приложений REST для Android была для меня огромным ресурсом. Динамик не показывает никакого кода, он просто рассматривает конструктивные соображения и методы, чтобы собрать рок-массив Rest Api в android. Если ваш подкаст какой-то человек или нет, я бы рекомендовал дать ему хотя бы один прослушивать, но лично я слушал его как 4 или пять раз, и, вероятно, я снова его послушаю.

Разработка клиентских приложений Android REST
Автор: Вергилий Добжанский
Описание:

На этом сеансе будут представлены архитектурные соображения для разработки приложений RESTful на платформе Android. Он фокусируется на шаблонах проектирования, интеграции платформы и производительности, характерных для платформы Android.

И есть так много соображений, которые я действительно не сделал в первой версии моего api, что мне пришлось реорганизовать





rest