Skip to content

Commit

Permalink
Make compatible with SDK 29 (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
KazuCocoa authored and dpgraham committed Mar 17, 2019
1 parent e92e653 commit 3883053
Show file tree
Hide file tree
Showing 20 changed files with 278 additions and 216 deletions.
16 changes: 10 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 19
buildToolsVersion "27.0.3"
compileSdkVersion 28
buildToolsVersion "28.0.3"

defaultConfig {
applicationId "io.appium.android.apis"
minSdkVersion 4
targetSdkVersion 19
minSdkVersion 17
targetSdkVersion 28

versionCode 2
versionName '3.0.0'
versionCode 17
versionName '4.0.0'

testApplicationId "io.appium.android.apis.test"
testInstrumentationRunner ".app.LocalSampleInstrumentation"
}

dependencies {
implementation 'androidx.appcompat:appcompat:1.0.2'
}

buildTypes {
release {
minifyEnabled false
Expand Down
16 changes: 9 additions & 7 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
own application, the package name must be changed from "com.example.*"
to come from a domain that you own or have control over. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="io.appium.android.apis">

<uses-permission android:name="android.permission.READ_CONTACTS" />
Expand All @@ -36,19 +37,20 @@
<!-- For android.media.audiofx.Visualizer -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="19" />

<!-- We will request access to the camera, saying we require a camera
of some sort but not one with autofocus capability. -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />

<application android:name="ApiDemosApplication"
android:label="@string/activity_sample_code"
android:icon="@drawable/app_sample_code"
android:hardwareAccelerated="true"
android:supportsRtl="true">
<application
android:name="ApiDemosApplication"
android:label="@string/activity_sample_code"
android:icon="@drawable/app_sample_code"
android:hardwareAccelerated="true"
android:supportsRtl="true"
tools:ignore="GoogleAppIndexingWarning"
android:allowBackup="false">

<!-- This is how we can request a library but still allow the app
to be installed if it doesn't exist. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@

// Need the following import to get access to the app resources, since this
// class is in a sub-package.
import androidx.core.app.NotificationCompat;
import io.appium.android.apis.R;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
Expand Down Expand Up @@ -98,19 +100,18 @@ public IBinder onBind(Intent intent) {
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.alarm_service_started);

// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.stat_sample, text,
System.currentTimeMillis());

// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, AlarmService.class), 0);

// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.alarm_service_label),
text, contentIntent);

Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.stat_sample) // the status icon
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.alarm_service_label)) // the label of the entry
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when the entry is clicked
.build();
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
mNM.notify(R.string.alarm_service_started, notification);
Expand Down
102 changes: 62 additions & 40 deletions app/src/main/java/io/appium/android/apis/app/ForegroundService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@

package io.appium.android.apis.app;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
Expand All @@ -46,24 +50,34 @@
*/
public class ForegroundService extends Service {
static final String ACTION_FOREGROUND = "io.appium.android.apis.FOREGROUND";
static final String ACTION_FOREGROUND_WAKELOCK = "io.appium.android.apis.FOREGROUND_WAKELOCK";
static final String ACTION_BACKGROUND = "io.appium.android.apis.BACKGROUND";

static final String ACTION_BACKGROUND_WAKELOCK = "io.appium.android.apis.BACKGROUND_WAKELOCK";

private PowerManager.WakeLock mWakeLock;
private Handler mHandler = new Handler();
private Runnable mPulser = new Runnable() {
@Override public void run() {
Log.i("ForegroundService", "PULSE!");
mHandler.postDelayed(this, 5*1000);
}
};

private static final Class<?>[] mSetForegroundSignature = new Class[] {
boolean.class};
private static final Class<?>[] mStartForegroundSignature = new Class[] {
int.class, Notification.class};
private static final Class<?>[] mStopForegroundSignature = new Class[] {
boolean.class};

private NotificationManager mNM;
private Method mSetForeground;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mSetForegroundArgs = new Object[1];
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];

void invokeMethod(Method method, Object[] args) {
try {
method.invoke(this, args);
Expand All @@ -75,7 +89,7 @@ void invokeMethod(Method method, Object[] args) {
Log.w("ApiDemos", "Unable to invoke method", e);
}
}

/**
* This is a wrapper around the new startForeground method, using the older
* APIs if it is not available.
Expand All @@ -88,13 +102,13 @@ void startForegroundCompat(int id, Notification notification) {
invokeMethod(mStartForeground, mStartForegroundArgs);
return;
}

// Fall back on the old API.
mSetForegroundArgs[0] = Boolean.TRUE;
invokeMethod(mSetForeground, mSetForegroundArgs);
mNM.notify(id, notification);
}

/**
* This is a wrapper around the new stopForeground method, using the older
* APIs if it is not available.
Expand All @@ -106,14 +120,14 @@ void stopForegroundCompat(int id) {
invokeMethod(mStopForeground, mStopForegroundArgs);
return;
}

// Fall back on the old API. Note to cancel BEFORE changing the
// foreground state, since we could be killed at that point.
mNM.cancel(id);
mSetForegroundArgs[0] = Boolean.FALSE;
invokeMethod(mSetForeground, mSetForegroundArgs);
}

@Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Expand Down Expand Up @@ -144,57 +158,65 @@ public void onDestroy() {



// This is the old onStart method that will be called on the pre-2.0
// platform. On 2.0 or later we override onStartCommand() so this
// method will not be called.
@Override
public void onStart(Intent intent, int startId) {
handleCommand(intent);
}

@SuppressLint("InvalidWakeLockTag")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}


void handleCommand(Intent intent) {
if (ACTION_FOREGROUND.equals(intent.getAction())) {
if (ACTION_FOREGROUND.equals(intent.getAction())
|| ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction())) {
// In this sample, we'll use the same text for the ticker and the expanded notification
CharSequence text = getText(R.string.foreground_service_started);

// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.stat_sample, text,
System.currentTimeMillis());

// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, Controller.class), 0);

// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, getText(R.string.local_service_label),
text, contentIntent);

Notification notification = new Notification.Builder(this)
.setSmallIcon(R.drawable.stat_sample) // the status icon
.setTicker(text) // the status text
.setWhen(System.currentTimeMillis()) // the time stamp
.setContentTitle(getText(R.string.alarm_service_label)) // the label
.setContentText(text) // the contents of the entry
.setContentIntent(contentIntent) // The intent to send when clicked
.build();
startForegroundCompat(R.string.foreground_service_started, notification);
} else if (ACTION_BACKGROUND.equals(intent.getAction())) {
} else if (ACTION_BACKGROUND.equals(intent.getAction())
|| ACTION_BACKGROUND_WAKELOCK.equals(intent.getAction())) {
stopForegroundCompat(R.string.foreground_service_started);
}
if (ACTION_FOREGROUND_WAKELOCK.equals(intent.getAction())
|| ACTION_BACKGROUND_WAKELOCK.equals(intent.getAction())) {
if (mWakeLock == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mWakeLock = getSystemService(PowerManager.class).newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "wake-service");
mWakeLock.acquire();
}
} else {
releaseWakeLock();
}
}
mHandler.removeCallbacks(mPulser);
mPulser.run();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}


void releaseWakeLock() {
if (mWakeLock != null) {
mWakeLock.release();
mWakeLock = null;
}
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

// ----------------------------------------------------------------------

/**
* <p>Example of explicitly starting and stopping the {@link ForegroundService}.
*
*
* <p>Note that this is implemented as an inner class only keep the sample
* all together; typically this code would appear in some separate class.
*/
Expand Down
Loading

0 comments on commit 3883053

Please sign in to comment.