Fix #583 (App crashes on Android 8)

This commit is contained in:
David Luhmer 2017-10-19 22:16:44 +02:00
parent 7e99577294
commit d22769d8dc
12 changed files with 153 additions and 111 deletions

View file

@ -113,7 +113,9 @@
**********************************************************************
-->
<service android:name=".services.DownloadImagesService" />
<service
android:name=".services.DownloadImagesService"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service android:name=".services.SyncItemStateService" />
<service

View file

@ -25,10 +25,10 @@ public class DownloadImagesActivity extends Activity {
.setCancelable(true)
.setPositiveButton(getString(android.R.string.yes) ,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
Intent service = new Intent(DownloadImagesActivity.this, DownloadImagesService.class);
service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemIdBeforeSync);
service.putExtra(DownloadImagesService.DOWNLOAD_MODE_STRING, DownloadImagesService.DownloadMode.PICTURES_ONLY);
DownloadImagesActivity.this.startService(service);
Intent data = new Intent();
data.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemIdBeforeSync);
data.putExtra(DownloadImagesService.DOWNLOAD_MODE_STRING, DownloadImagesService.DownloadMode.PICTURES_ONLY);
DownloadImagesService.enqueueWork(DownloadImagesActivity.this, data);
DownloadImagesActivity.this.finish();
}

View file

@ -187,7 +187,7 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
}
};
drawerLayout.setDrawerListener(drawerToggle);
drawerLayout.addDrawerListener(drawerToggle);
try {
// increase the size of the drag margin to prevent starting a star swipe when
@ -476,7 +476,7 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
// Setting android:TextColor to #000 in the light theme results in black on black
// text on the Snackbar, set the text back to white,
// TODO: find a cleaner way to do this
TextView textView = (TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
TextView textView = snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
textView.setTextColor(Color.WHITE);
snackbar.show();
}
@ -537,10 +537,11 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getApplicationContext());
if (isFolder) {
/*
if(idFeed >= 0) {
//currently no actions for folders
//String titel = dbConn.getFolderById(idFeed).getLabel();
}
}*/
} else {
String titel = dbConn.getFeedById(idFeed).getFeedTitle();
String iconurl = dbConn.getFeedById(idFeed).getFaviconUrl();
@ -612,9 +613,9 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
{
SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
if(mPrefs.getString(SettingsActivity.EDT_OWNCLOUDROOTPATH_STRING, null) == null)
if(mPrefs.getString(SettingsActivity.EDT_OWNCLOUDROOTPATH_STRING, null) == null) {
StartLoginFragment(this);
else {
} else {
if (!ownCloudSyncService.isSyncRunning())
{
new PostDelayHandler(this).stopRunningPostDelayHandler();//Stop pending sync handler
@ -630,7 +631,6 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
} else {
UpdateButtonLayout();
}
}
}
@ -721,10 +721,12 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this);
long highestItemId = dbConn.getLowestRssItemIdUnread();
Intent service = new Intent(this, DownloadImagesService.class);
service.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemId);
service.putExtra(DownloadImagesService.DOWNLOAD_MODE_STRING, DownloadImagesService.DownloadMode.PICTURES_ONLY);
startService(service);
Intent data = new Intent();
data.putExtra(DownloadImagesService.LAST_ITEM_ID, highestItemId);
data.putExtra(DownloadImagesService.DOWNLOAD_MODE_STRING, DownloadImagesService.DownloadMode.PICTURES_ONLY);
DownloadImagesService.enqueueWork(this, data);
break;

View file

@ -34,37 +34,35 @@ import java.net.URL;
import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished;
public class GetImageThreaded implements ImageLoadingListener
public class DownloadImageHandler implements ImageLoadingListener
{
private static final String TAG = "GetImageAsyncTask";
private URL WEB_URL_TO_FILE;
private URL mImageUrl;
private ImageDownloadFinished imageDownloadFinished;
private long ThreadId;
private static final DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder()
.cacheOnDisk(true)
.build();
public GetImageThreaded(String WEB_URL_TO_FILE, ImageDownloadFinished imgDownloadFinished, long ThreadId) {
try
{
this.WEB_URL_TO_FILE = new URL(WEB_URL_TO_FILE);
}
catch(Exception ex)
{
Log.d(TAG, "Invalid URL: " + WEB_URL_TO_FILE, ex);
public DownloadImageHandler(String imageUrl) {
try {
this.mImageUrl = new URL(imageUrl);
} catch(Exception ex) {
Log.d(TAG, "Invalid URL: " + imageUrl, ex);
}
imageDownloadFinished = imgDownloadFinished;
this.ThreadId = ThreadId;
//this.imageViewReference = new WeakReference<ImageView>(imageView);
}
public void start() {
ImageLoader.getInstance().loadImage(WEB_URL_TO_FILE.toString(), displayImageOptions, this);
}
public void downloadSync() {
ImageLoader.getInstance().loadImageSync(mImageUrl.toString(), displayImageOptions);
}
public void downloadAsync(ImageDownloadFinished imgDownloadFinished) {
this.imageDownloadFinished = imgDownloadFinished;
ImageLoader.getInstance().loadImage(mImageUrl.toString(), displayImageOptions, this);
}
@Override
public void onLoadingStarted(String imageUri, View view) {
@ -89,7 +87,8 @@ public class GetImageThreaded implements ImageLoadingListener
}
private void NotifyDownloadFinished(Bitmap bitmap) {
if(imageDownloadFinished != null)
imageDownloadFinished.DownloadFinished(ThreadId, bitmap);
if(imageDownloadFinished != null) {
imageDownloadFinished.DownloadFinished(bitmap);
}
}
}

View file

@ -19,7 +19,7 @@ public class PodcastNotificationToggle extends BroadcastReceiver {
//TODO problem: only the headphone unplug event is triggered. Somehow the headphone plug-in event is not triggered at all..
//TODO expected: receive the headphone plug-in event and trigger the "play" event
if(intent.getAction().equals("android.media.AUDIO_BECOMING_NOISY")) {
if(intent.getAction() != null && intent.getAction().equals("android.media.AUDIO_BECOMING_NOISY")) {
EventBus.getDefault().post(new TogglePlayerStateEvent(TogglePlayerStateEvent.State.Pause));
} else {
EventBus.getDefault().post(new TogglePlayerStateEvent());

View file

@ -25,5 +25,5 @@ package de.luhmer.owncloudnewsreader.helper;
import android.graphics.Bitmap;
public interface ImageDownloadFinished {
void DownloadFinished(long AsynkTaskId, Bitmap bitmap);
void DownloadFinished(Bitmap bitmap);
}

View file

@ -1,5 +1,6 @@
package de.luhmer.owncloudnewsreader.helper;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
@ -10,18 +11,20 @@ import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
import de.luhmer.owncloudnewsreader.R;
public class NotificationManagerNewsReader {
private static NotificationManagerNewsReader instance;
private final int NOTIFICATION_ID = 0;
private final String CHANNEL_ID = "0";
private Context context;
public static NotificationManagerNewsReader getInstance(Context context)
public synchronized static NotificationManagerNewsReader getInstance(Context context)
{
if(instance == null)
instance = new NotificationManagerNewsReader(context);
return instance;
}
public NotificationManagerNewsReader(Context context)
private NotificationManagerNewsReader(Context context)
{
this.context = context;
//NOTIFICATION_ID = new Random().nextInt();
@ -33,7 +36,7 @@ public class NotificationManagerNewsReader {
public void ShowMessage(String title, String tickerMessage, String message)
{
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context)
new NotificationCompat.Builder(context, "")
.setSmallIcon(R.drawable.ic_notification)
.setTicker(tickerMessage)
.setContentTitle(title)
@ -63,6 +66,15 @@ public class NotificationManagerNewsReader {
// Add as notification
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, importance);
//mChannel.enableLights(true);
manager.createNotificationChannel(mChannel);
builder.setChannelId(CHANNEL_ID);
}
manager.notify(NOTIFICATION_ID, builder.build());
}

View file

@ -21,14 +21,16 @@
package de.luhmer.owncloudnewsreader.services;
import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.ImageLoader;
@ -41,37 +43,48 @@ import java.util.Random;
import de.greenrobot.dao.query.LazyList;
import de.luhmer.owncloudnewsreader.NewsReaderListActivity;
import de.luhmer.owncloudnewsreader.R;
import de.luhmer.owncloudnewsreader.async_tasks.GetImageThreaded;
import de.luhmer.owncloudnewsreader.async_tasks.DownloadImageHandler;
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
import de.luhmer.owncloudnewsreader.database.model.Feed;
import de.luhmer.owncloudnewsreader.database.model.RssItem;
import de.luhmer.owncloudnewsreader.helper.FavIconHandler;
import de.luhmer.owncloudnewsreader.helper.ImageDownloadFinished;
import de.luhmer.owncloudnewsreader.helper.ImageHandler;
public class DownloadImagesService extends IntentService {
public class DownloadImagesService extends JobIntentService {
public static final String LAST_ITEM_ID = "LAST_ITEM_ID";
private static final String TAG = DownloadImagesService.class.getCanonicalName();
public enum DownloadMode { FAVICONS_ONLY, PICTURES_ONLY, FAVICONS_AND_PICTURES }
public static final String DOWNLOAD_MODE_STRING = "DOWNLOAD_MODE";
private static Random random;
private int NOTIFICATION_ID = 1;
private NotificationManager notificationManager;
private NotificationManager mNotificationManager;
private NotificationCompat.Builder mNotificationDownloadImages;
NotificationChannel mChannel;
private int maxCount;
private int maxCount;
//private int total_size = 0;
List<String> linksToImages = new LinkedList<>();
public DownloadImagesService() {
super(null);
}
public DownloadImagesService(String name) {
super(name);
}
/**
* Unique job/channel ID for this service.
*/
static final int JOB_ID = 1000;
static final String CHANNEL_ID = "1000";
/**
* Convenience method for enqueuing work in to this service.
*/
public static void enqueueWork(Context context, Intent work) {
enqueueWork(context, DownloadImagesService.class, JOB_ID, work);
}
@Override
public void onCreate() {
@ -84,23 +97,32 @@ public class DownloadImagesService extends IntentService {
} catch (Exception ex) {
ex.printStackTrace();
}
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
mChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, importance);
//mChannel.enableLights(true);
mNotificationManager.createNotificationChannel(mChannel);
}
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
if(mNotificationDownloadImages != null)
{
if(maxCount == 0)
notificationManager.cancel(NOTIFICATION_ID);
mNotificationManager.cancel(NOTIFICATION_ID);
}
super.onDestroy();
}
@Override
protected void onHandleIntent(Intent intent) {
@Override
protected void onHandleWork(@NonNull Intent intent) {
DownloadMode downloadMode = (DownloadMode) intent.getSerializableExtra(DOWNLOAD_MODE_STRING);
DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this);
Notification notify = BuildNotification();
@ -119,7 +141,7 @@ public class DownloadImagesService extends IntentService {
links.addAll(ImageHandler.getImageLinksFromText(body));
if(links.size() > 10000) {
notificationManager.notify(123, GetNotificationLimitImagesReached(10000));
mNotificationManager.notify(123, GetNotificationLimitImagesReached(10000));
break;
}
}
@ -128,20 +150,22 @@ public class DownloadImagesService extends IntentService {
maxCount = links.size();
if (maxCount > 0) {
notificationManager.notify(NOTIFICATION_ID, notify);
mNotificationManager.notify(NOTIFICATION_ID, notify);
}
linksToImages.addAll(links);
StartNextDownloadInQueue();
downloadImages();
}
}
private synchronized void StartNextDownloadInQueue() {
private void downloadImages() {
try {
if(linksToImages.size() > 0) {
while(linksToImages.size() > 0) {
String link = linksToImages.remove(0);
new GetImageThreaded(link, imgDownloadFinished, 999).start();
new DownloadImageHandler(link).downloadSync();
updateNotificationProgress();
}
} catch (Exception ex) {
ex.printStackTrace();
@ -149,15 +173,34 @@ public class DownloadImagesService extends IntentService {
}
}
private void updateNotificationProgress() {
int count = maxCount - linksToImages.size();
if(maxCount == count) {
mNotificationManager.cancel(NOTIFICATION_ID);
//RemoveOldImages();
} else {
mNotificationDownloadImages
.setContentText("Downloading Images for offline usage - " + (count + 1) + "/" + maxCount)
.setProgress(maxCount, count + 1, false);
mNotificationManager.notify(NOTIFICATION_ID, mNotificationDownloadImages.build());
}
}
private Notification GetNotificationLimitImagesReached(int limit) {
Intent intentNewsReader = new Intent(this, NewsReaderListActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intentNewsReader, 0);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this)
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Nextcloud News")
.setContentText("Only " + limit + " images can be cached at once")
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(pIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
notifyBuilder.setChannelId(CHANNEL_ID);
}
Notification notify = notifyBuilder.build();
//Hide the notification after its selected
@ -168,14 +211,17 @@ public class DownloadImagesService extends IntentService {
private Notification BuildNotification() {
Intent intentNewsReader = new Intent(this, NewsReaderListActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intentNewsReader, 0);
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationDownloadImages = new NotificationCompat.Builder(this)
mNotificationDownloadImages = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(getResources().getString(R.string.app_name))
.setContentText("Downloading images for offline usage")
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(pIntent)
.setOngoing(true);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mNotificationDownloadImages.setChannelId(CHANNEL_ID);
}
Notification notify = mNotificationDownloadImages.build();
//Hide the notification after its selected
@ -189,24 +235,4 @@ public class DownloadImagesService extends IntentService {
ImageLoader.getInstance().clearDiskCache();
}
ImageDownloadFinished imgDownloadFinished = new ImageDownloadFinished() {
@Override
public void DownloadFinished(long AsynkTaskId, Bitmap bitmap) {
int count = maxCount - linksToImages.size();
if(maxCount == count) {
notificationManager.cancel(NOTIFICATION_ID);
//RemoveOldImages();
} else {
mNotificationDownloadImages
.setContentText("Downloading Images for offline usage - " + (count + 1) + "/" + maxCount)
.setProgress(maxCount, count + 1, false);
notificationManager.notify(NOTIFICATION_ID, mNotificationDownloadImages.build());
StartNextDownloadInQueue();
}
}
};
}

View file

@ -146,13 +146,11 @@ public class OwnCloudSyncService extends Service {
boolean stateSyncSuccessful;
}
//Sync state of items e.g. read/unread/starred/unstarred
// Start sync
private void start() {
syncStopWatch = new StopWatch();
syncStopWatch.start();
//Delete all pinned/stored SSL Certificates
/*
final ArrayList<String> aliases = Collections.list(mMTM.getCertificates());
@ -164,15 +162,8 @@ public class OwnCloudSyncService extends Service {
}
}*/
final DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(OwnCloudSyncService.this);
Observable rssStateSync = Observable.fromPublisher(
new Publisher() {
@Override
@ -316,10 +307,9 @@ public class OwnCloudSyncService extends Service {
}
}
Intent service = new Intent(this, DownloadImagesService.class);
service.setPackage(getPackageName());
service.putExtra(DownloadImagesService.DOWNLOAD_MODE_STRING, DownloadImagesService.DownloadMode.FAVICONS_ONLY);
startService(service);
Intent data = new Intent();
data.putExtra(DownloadImagesService.DOWNLOAD_MODE_STRING, DownloadImagesService.DownloadMode.FAVICONS_ONLY);
DownloadImagesService.enqueueWork(OwnCloudSyncService.this, data);
EventBus.getDefault().post(new SyncFinishedEvent());
}

View file

@ -1,22 +1,19 @@
package de.luhmer.owncloudnewsreader.view;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.session.MediaSessionManager;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@ -43,10 +40,12 @@ public class PodcastNotification {
private EventBus eventBus;
private NotificationCompat.Builder notificationBuilder;
private PendingIntent resultPendingIntent;
private String CHANNEL_ID = "1";
private MediaSessionManager mManager;
public MediaSessionCompat mSession;
private MediaControllerCompat mController;
//private MediaSessionManager mManager;
private MediaSessionCompat mSession;
//private MediaControllerCompat mController;
private int lastDrawableId = -1;
private final static int NOTIFICATION_ID = 1111;
@ -54,6 +53,13 @@ public class PodcastNotification {
this.mContext = context;
this.notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, importance);
//mChannel.enableLights(true);
this.notificationManager.createNotificationChannel(mChannel);
}
eventBus = EventBus.getDefault();
eventBus.register(this);
}
@ -78,16 +84,18 @@ public class PodcastNotification {
);
// Create the final Notification object.
notificationBuilder = new NotificationCompat.Builder(mContext)
notificationBuilder = new NotificationCompat.Builder(mContext, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setAutoCancel(true)
.setOngoing(true)
.setContentIntent(resultPendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
notificationBuilder.setChannelId(CHANNEL_ID);
}
}
int lastDrawableId = -1;
@Subscribe
public void onEvent(UpdatePodcastStatusEvent podcast) {
if(mSession == null)
@ -216,6 +224,8 @@ public class PodcastNotification {
}
}, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
//MediaControllerCompat controller = mSession.getController();
mSession.setActive(true);

View file

@ -14,5 +14,6 @@ allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
maven { url "https://maven.google.com" }
}
}

View file

@ -19,5 +19,5 @@
ANDROID_BUILD_MIN_SDK_VERSION=17
ANDROID_BUILD_TARGET_SDK_VERSION=26
ANDROID_BUILD_TOOLS_VERSION=25.0.3
ANDROID_BUILD_SDK_VERSION=25
ANDROID_BUILD_TOOLS_VERSION=26.0.2
ANDROID_BUILD_SDK_VERSION=26