New API demo for isolated processes.

Change-Id: I2b2117ae5e5005bfffe8d89df5e06cee32da603c
This commit is contained in:
Dianne Hackborn
2012-02-09 10:51:07 -08:00
parent 86fa7ead3f
commit 37f02d8042
7 changed files with 383 additions and 0 deletions

View File

@@ -519,6 +519,21 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".app.IsolatedService$Controller"
android:label="@string/activity_isolated_service_controller"
android:launchMode="singleTop"
android:enabled="@bool/atLeastJellyBean">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
<service android:name=".app.IsolatedService" android:isolatedProcess="true"
android:enabled="@bool/atLeastJellyBean" />
<service android:name=".app.IsolatedService2" android:isolatedProcess="true"
android:enabled="@bool/atLeastJellyBean" />
<!-- Alarm Samples --> <!-- Alarm Samples -->
<receiver android:name=".app.OneShotAlarm" android:process=":remote" /> <receiver android:name=".app.OneShotAlarm" android:process=":remote" />

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Demonstrates isolated services.
See corresponding Java code com.android.sdk.app.IsolatedSerice.java. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:padding="4dip"
android:gravity="center_horizontal"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingBottom="4dip"
android:gravity="center_vertical|center_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/isolated_service_controller"/>
<LinearLayout android:orientation="horizontal" android:paddingTop="16dp"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<Button android:id="@+id/start1"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/start_service_1">
<requestFocus />
</Button>
<Button android:id="@+id/stop1"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/stop_service_1">
</Button>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<CheckBox android:id="@+id/bind1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bind_service_1" />
<TextView android:id="@+id/status1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="16dp" />
</LinearLayout>
<LinearLayout android:orientation="horizontal" android:paddingTop="16dp"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<Button android:id="@+id/start2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/start_service_2">
<requestFocus />
</Button>
<Button android:id="@+id/stop2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="@string/stop_service_2">
</Button>
</LinearLayout>
<LinearLayout android:orientation="horizontal"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<CheckBox android:id="@+id/bind2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bind_service_2" />
<TextView android:id="@+id/status2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="16dp" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- True if running under JellyBean or later. -->
<bool name="atLeastJellyBean">true</bool>
</resources>

View File

@@ -29,4 +29,9 @@
for IceCreamSandwich is true. --> for IceCreamSandwich is true. -->
<bool name="atLeastIceCreamSandwich">false</bool> <bool name="atLeastIceCreamSandwich">false</bool>
<!-- This resource is true if running under at least JellyBean
API level. The default value is false; an alternative value
for JellyBean is true. -->
<bool name="atLeastJellyBean">false</bool>
</resources> </resources>

View File

@@ -239,6 +239,20 @@
<string name="start_service_foreground">Start Service Foreground</string> <string name="start_service_foreground">Start Service Foreground</string>
<string name="start_service_background">Start Service Background</string> <string name="start_service_background">Start Service Background</string>
<string name="activity_isolated_service_controller">App/Service/Isolated Service Controller</string>
<string name="isolated_service_controller">This demonstrates the use of android:isolatedProcess
with services. There are two services, which can be independently controlled; they will
each run in their own isolated process</string>
<string name="start_service_1">Start Service 1</string>
<string name="stop_service_1">Stop Service 1</string>
<string name="bind_service_1">Bind Service 1</string>
<string name="start_service_2">Start Service 2</string>
<string name="stop_service_2">Stop Service 2</string>
<string name="bind_service_2">Bind Service 2</string>
<string name="isolated_service_1_started">Isolated service 1 has started</string>
<string name="isolated_service_1_stopped">Isolated service 1 has stopped</string>
<string name="isolated_service_1_label">Sample Isolated Service 1</string>
<string name="one_shot_received">The one-shot alarm has gone off</string> <string name="one_shot_received">The one-shot alarm has gone off</string>
<string name="repeating_received">The repeating alarm has gone off</string> <string name="repeating_received">The repeating alarm has gone off</string>

View File

@@ -0,0 +1,217 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.apis.app;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import com.example.android.apis.R;
/**
* This is an example if implementing a Service that uses android:isolatedProcess.
*/
public class IsolatedService extends Service {
/**
* This is a list of callbacks that have been registered with the
* service. Note that this is package scoped (instead of private) so
* that it can be accessed more efficiently from inner classes.
*/
final RemoteCallbackList<IRemoteServiceCallback> mCallbacks
= new RemoteCallbackList<IRemoteServiceCallback>();
int mValue = 0;
NotificationManager mNM;
@Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// Tell the user we stopped.
Toast.makeText(this, R.string.isolated_service_1_started, Toast.LENGTH_SHORT).show();
}
@Override
public void onDestroy() {
// Tell the user we stopped.
Toast.makeText(this, R.string.isolated_service_1_stopped, Toast.LENGTH_SHORT).show();
// Unregister all callbacks.
mCallbacks.kill();
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* The IRemoteInterface is defined through IDL
*/
private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
public void registerCallback(IRemoteServiceCallback cb) {
if (cb != null) mCallbacks.register(cb);
}
public void unregisterCallback(IRemoteServiceCallback cb) {
if (cb != null) mCallbacks.unregister(cb);
}
};
@Override
public void onTaskRemoved(Intent rootIntent) {
Toast.makeText(this, "Task removed: " + rootIntent, Toast.LENGTH_LONG).show();
stopSelf();
}
private void broadcastValue(int value) {
// Broadcast to all clients the new value.
final int N = mCallbacks.beginBroadcast();
for (int i=0; i<N; i++) {
try {
mCallbacks.getBroadcastItem(i).valueChanged(value);
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
mCallbacks.finishBroadcast();
}
// ----------------------------------------------------------------------
public static class Controller extends Activity {
static class ServiceInfo {
final Activity mActivity;
final Class mClz;
final TextView mStatus;
boolean mServiceBound;
IRemoteService mService;
ServiceInfo(Activity activity, Class clz, int start, int stop, int bind, int status) {
mActivity = activity;
mClz = clz;
Button button = (Button)mActivity.findViewById(start);
button.setOnClickListener(mStartListener);
button = (Button)mActivity.findViewById(stop);
button.setOnClickListener(mStopListener);
CheckBox cb = (CheckBox)mActivity.findViewById(bind);
cb.setOnClickListener(mBindListener);
mStatus = (TextView)mActivity.findViewById(status);
}
void destroy() {
if (mServiceBound) {
mActivity.unbindService(mConnection);
}
}
private OnClickListener mStartListener = new OnClickListener() {
public void onClick(View v) {
mActivity.startService(new Intent(mActivity, mClz));
}
};
private OnClickListener mStopListener = new OnClickListener() {
public void onClick(View v) {
mActivity.stopService(new Intent(mActivity, mClz));
}
};
private OnClickListener mBindListener = new OnClickListener() {
public void onClick(View v) {
if (((CheckBox)v).isChecked()) {
if (!mServiceBound) {
if (mActivity.bindService(new Intent(mActivity, mClz),
mConnection, Context.BIND_AUTO_CREATE)) {
mServiceBound = true;
mStatus.setText("BOUND");
}
}
} else {
if (mServiceBound) {
mActivity.unbindService(mConnection);
mServiceBound = false;
mStatus.setText("");
}
}
}
};
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
mService = IRemoteService.Stub.asInterface(service);
if (mServiceBound) {
mStatus.setText("CONNECTED");
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
if (mServiceBound) {
mStatus.setText("DISCONNECTED");
}
}
};
}
ServiceInfo mService1;
ServiceInfo mService2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.isolated_service_controller);
mService1 = new ServiceInfo(this, IsolatedService.class, R.id.start1, R.id.stop1,
R.id.bind1, R.id.status1);
mService2 = new ServiceInfo(this, IsolatedService2.class, R.id.start2, R.id.stop2,
R.id.bind2, R.id.status2);
}
@Override
protected void onDestroy() {
super.onDestroy();
mService1.destroy();
mService2.destroy();
}
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.apis.app;
/**
* Stub to be able to have another instance of IsolatedService running.
*/
public class IsolatedService2 extends IsolatedService {
}