• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.soundpicker;
18 
19 import android.app.Service;
20 import android.content.Intent;
21 import android.media.RingtoneManager;
22 import android.net.Uri;
23 import android.os.AsyncTask;
24 import android.os.Environment;
25 import android.os.FileUtils;
26 import android.os.IBinder;
27 import android.provider.MediaStore;
28 import android.provider.Settings.System;
29 import android.util.Log;
30 
31 import androidx.annotation.IdRes;
32 import androidx.annotation.NonNull;
33 import androidx.annotation.Nullable;
34 
35 import java.io.File;
36 import java.io.FileOutputStream;
37 import java.io.IOException;
38 import java.io.InputStream;
39 
40 /**
41  * Service to copy and set customization of default sounds
42  */
43 public class RingtoneOverlayService extends Service {
44     private static final String TAG = "RingtoneOverlayService";
45     private static final boolean DEBUG = false;
46 
47     @Override
onStartCommand(@ullable final Intent intent, final int flags, final int startId)48     public int onStartCommand(@Nullable final Intent intent, final int flags, final int startId) {
49         AsyncTask.execute(() -> {
50             updateRingtones();
51             stopSelf();
52         });
53 
54         // Try again later if we are killed before we finish.
55         return Service.START_REDELIVER_INTENT;
56     }
57 
58     @Override
onBind(@ullable final Intent intent)59     public IBinder onBind(@Nullable final Intent intent) {
60         return null;
61     }
62 
updateRingtones()63     private void updateRingtones() {
64         copyResourceAndSetAsSound(R.raw.default_ringtone,
65                 System.RINGTONE, Environment.DIRECTORY_RINGTONES);
66         copyResourceAndSetAsSound(R.raw.default_notification_sound,
67                 System.NOTIFICATION_SOUND, Environment.DIRECTORY_NOTIFICATIONS);
68         copyResourceAndSetAsSound(R.raw.default_alarm_alert,
69                 System.ALARM_ALERT, Environment.DIRECTORY_ALARMS);
70     }
71 
72     /* If the resource contains any data, copy a resource to the file system, scan it, and set the
73      * file URI as the default for a sound. */
copyResourceAndSetAsSound(@dRes final int id, @NonNull final String name, @NonNull final String subPath)74     private void copyResourceAndSetAsSound(@IdRes final int id, @NonNull final String name,
75             @NonNull final String subPath) {
76         final File destDir = Environment.getExternalStoragePublicDirectory(subPath);
77         if (!destDir.exists() && !destDir.mkdirs()) {
78             Log.e(TAG, "can't create " + destDir.getAbsolutePath());
79             return;
80         }
81 
82         final File dest = new File(destDir, "default_" + name + ".ogg");
83         try (
84             InputStream is = getResources().openRawResource(id);
85             FileOutputStream os = new FileOutputStream(dest);
86         ) {
87             if (is.available() > 0) {
88                 FileUtils.copy(is, os);
89                 final Uri uri = scanFile(dest);
90                 if (uri != null) {
91                     set(name, uri);
92                 }
93             } else {
94                 // TODO Shall we remove any former copied resource in this case and unset
95                 // the defaults if we use this event a second time to clear the data?
96                 if (DEBUG) Log.d(TAG, "Resource for " + name + " has no overlay");
97             }
98         } catch (IOException e) {
99             Log.e(TAG, "Unable to open resource for " + name + ": " + e);
100         }
101     }
102 
scanFile(@onNull final File file)103     private Uri scanFile(@NonNull final File file) {
104         return MediaStore.scanFile(getContentResolver(), file);
105     }
106 
set(@onNull final String name, @NonNull final Uri uri)107     private void set(@NonNull final String name, @NonNull final Uri uri) {
108         final Uri settingUri = System.getUriFor(name);
109         RingtoneManager.setActualDefaultRingtoneUri(this,
110                 RingtoneManager.getDefaultType(settingUri), uri);
111         System.putInt(getContentResolver(), name + "_set", 1);
112     }
113 }
114