I developed an android app using android download manager and Broadcast receiver, after completed downloading I am passing success response to BroadcastReceiver class but that not calling. What I did wrong?
public class MobuleDownloadManager {
private boolean isReaname = false;
private ProgressDialog mProgressDialog;
private Activity activity;
private DownloadFile mDownloadClas;
private String TAG = "MobuleDownloadManager", URL, mFileName, mDisplayName_;
private AlertDialog alert;
private DownloadManager downloadManager;
private long enqueue, id;
SharedPreferences preferenceManager;
final String strPref_Download_ID = "PREF_DOWNLOAD_ID";
public static BroadcastReceiver downloadReceiver = null;
final Timer myTimer = new Timer();
Cursor cursorMain, cursorTimer;
private SharedPreferences.Editor PrefEdit;
int bytes_total;
public MobuleDownloadManager(final Activity activity_, String mFilePath_,
final String mFileName_, final String mDisplayName) {
super();
this.URL = mFilePath_;
fileDownloadManager(URL);
FileInputStream in = null;
try {
in = activity.openFileInput(mFileName);
// file is alredy exist so no need too download again just open file
myTimer.cancel();
OnHttpResponseDownloadFile callBack = (OnHttpResponseDownloadFile) activity;
callBack.onSuccessDownloadFile(mFileName, mDisplayName_);
fileDownloadManager(URL);
} catch (FileNotFoundException e1) {
try {
fileDownloadManager(URL);
}
}
private void fileDownloadManager(String url) {
preferenceManager = PreferenceManager.getDefaultSharedPreferences(activity);
downloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(downloadUri);
id = downloadManager.enqueue(request);
mProgressDialog = new ProgressDialog(activity);
mProgressDialog.setTitle("Downloading");
mProgressDialog.setMessage("Downloading, Please Wait!");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setCancelable(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
"Cancel", new DialogInterface.OnClickListener() {
// Set a click listener for progress dialog cancel
// button
#Override
public void onClick(DialogInterface dialog, int which) {
try {
myTimer.cancel();
downloadManager.remove(id);
mProgressDialog.dismiss();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
});
mProgressDialog.show();
PrefEdit = preferenceManager.edit();
PrefEdit.putLong(strPref_Download_ID, id);
PrefEdit.commit();
myTimer.schedule(new TimerTask() {
public void run() {
try {
DownloadManager.Query q;
q = new DownloadManager.Query();
q.setFilterById(preferenceManager.getLong(strPref_Download_ID, 0));
cursorTimer = downloadManager.query(q);
if (cursorTimer.moveToFirst() && cursorTimer != null) {
Log.e("bytes_total", "cursorTimer");
int bytes_downloaded = cursorTimer.getInt(cursorTimer.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
bytes_total = cursorTimer.getInt(cursorTimer.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
final int dl_progress = (int) ((double) bytes_downloaded / (double) bytes_total * 100f);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mProgressDialog.setProgress(dl_progress);
}
});
if (bytes_total == bytes_downloaded) {
Log.e(TAG, "run block 1");
myTimer.cancel();
mProgressDialog.dismiss();
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
activity.registerReceiver(downloadReceiver, intentFilter);
Log.e(TAG, "run block 2");
}
} else {
}
} catch (Exception e) {
Log.e(TAG, "Exception:" + e.getMessage());
} finally {
Log.e(TAG, "finally");
cursorTimer.close();
}
}
}, 0, 1000);
try {
Log.e(TAG, "BroadcastReceiver ");
downloadReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG, "BroadcastReceiver onReceive");
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(preferenceManager.getLong(strPref_Download_ID, 0));
cursorMain = downloadManager.query(query);
Log.e(TAG, "BroadcastReceiver " + cursorMain.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (cursorMain.moveToFirst()) {
int columnIndex = cursorMain.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursorMain.getInt(columnIndex);
if (status == DownloadManager.STATUS_SUCCESSFUL) {
ParcelFileDescriptor file;
try {
file = downloadManager.openDownloadedFile(preferenceManager.getLong(strPref_Download_ID, 0));
InputStream fileStream = new FileInputStream(file.getFileDescriptor());
FileOutputStream newOS = null;
if (isReaname) {
newOS = activity.openFileOutput("encrypted$" + mFileName, Context.MODE_PRIVATE);
} else {
newOS = activity.openFileOutput(mFileName, Context.MODE_PRIVATE);
}
byte[] buffer = new byte[1024];
int length;
while ((length = fileStream.read(buffer)) > 0) {
newOS.write(buffer, 0, length);
}
newOS.flush();
fileStream.close();
newOS.close();
downloadManager.remove(id);
activity.unregisterReceiver(downloadReceiver);
PrefEdit.clear();
OnHttpResponseDownloadFile callBack = (OnHttpResponseDownloadFile) activity;
callBack.onSuccessDownloadFile(mFileName, mDisplayName_);
} catch (Exception e) {
}
} else {
downloadManager.remove(id);
activity.unregisterReceiver(downloadReceiver);
}
}
}
};
} catch (Exception e) {
} finally {
}
}
}
declaration:
public static DownloadReciver downloadReceiver = new DownloadReciver();
Now this is my reciver class
public static class DownloadReciver extends BroadcastReceiver {
public DownloadReciver() {
super();
}
#Override
public void onReceive(Context context, Intent intent) {
}
}
I am calling like this:
if (bytes_total == bytes_downloaded) {
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
activity.registerReceiver(downloadReceiver, intentFilter);
}
this is my manifest:
<receiver android:name="com.mobule.lms.connection.MobuleDownloadManager$DownloadReciver" >
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
I got Exception:
java.lang.RuntimeException: Unable to start receiver com.mobule.lms.connection.MobuleDownloadManager$DownloadReciver: java.lang.NullPointerException
Did you declare BroadcastReceiver in your Manifest?
Declare Receiver in Manifest, Check Android 6.0 Marshmallow Permissions given or not and Check uses-permissions provided or not.
For Inner Class also we can Declare in Manifest:
The receiver android:name attribute should look like .path.to.class.MyClass$MyInnerClass
You Should Register your broadcast receiver as the following
<receiver android:name=".path.to.your.downloadReciever" >
<intent-filter>
<action android:name="your filter" />
</intent-filter>
</receiver>
Related
I am downloading multiple files one after the other in service. I want to update download progress in notification. But my notification doesn't update when I kill my app. Download works on different thread. Download works fine in when app is running. When I kill app from recent section, I am unable to update notification.
Here is my DownloadService class
public class DownloadService extends Service {
public static DownloadMap<String, Downloadables> map = new DownloadMap<String, Downloadables>();
private static Thread thread;
private DownloadCancelReceiver receiver;
public DownloadService() {
}
public class BackgroundThread extends Thread {
int serviceId;
private DownloadMap<String, Downloadables> map;
private SpeedRevisionDatabase helper;
private final int notificationId = 1;
private RemoteViews remoteViewsSmall, remoteViewsBig;
private NotificationManagerCompat notificationManager;
private NotificationCompat.Builder mBuilder, mBuilderComplete, downloadFailBuilder;
public BackgroundThread(int serviceId, DownloadMap<String, Downloadables> map) {
this.serviceId = serviceId;
this.map = new DownloadMap<>();
this.map.putAll(map);
}
#Override
public void run() {
remoteViewsSmall = new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_notification_small);
remoteViewsBig = new RemoteViews(getApplicationContext().getPackageName(), R.layout.download_notification);
Intent cancelDownload = new Intent("CANCEL_DOWNLOAD");
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 100, cancelDownload, 0);
remoteViewsBig.setOnClickPendingIntent(R.id.tvCancel, pendingIntent);
notificationManager = NotificationManagerCompat.from(DownloadService.this);
mBuilder = new NotificationCompat.Builder(DownloadService.this, "default");
initChannels(DownloadService.this);
mBuilder.setContentTitle("Download is in progress")
.setContentText("Please wait...")
.setSmallIcon(R.mipmap.download)
.setOngoing(true)
.setCustomContentView(remoteViewsSmall)
.setCustomBigContentView(remoteViewsBig)
.setPriority(NotificationCompat.PRIORITY_HIGH);
notificationManager.notify(notificationId, mBuilder.build());
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
try {
String path = getApplicationContext().getApplicationInfo().dataDir + "/" + "UEP";
File uepFolder = new File(path);
if (!uepFolder.exists()) {
uepFolder.mkdir();
}
int i = 0;
while (map.entrySet().iterator().hasNext()) {
Log.e("WhileCheck", "Now i is " + i);
Map.Entry data = (Map.Entry) map.entrySet().iterator().next();
try {
Downloadables download = (Downloadables) data.getValue();
if (NetworkUtil.getConnectivityStatus(getApplicationContext()) == 0) {
throw new InternetDisconnectedException("Internet Disconnected");
}
HttpURLConnection urlConnection;
InputStream inputStream;
//finding file on internet
try {
URL url = new URL(download.URL);
if (url.toString().endsWith(".xps")) {
url = new URL(url.toString().replace(".xps", ".pdf"));
}
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
inputStream = urlConnection.getInputStream();
} catch (IOException e) {
Log.e("IOException", "" + e.getMessage());
i++;
map.remove(data.getKey());
notificationManager.notify(notificationId, mBuilder.build());
continue;
}
//Downloading file over internet
File file = new File(uepFolder + "/" + download.FileName + "" + download.Format + ".download");
try {
int fileSize = urlConnection.getContentLength();
FileOutputStream fileOutput = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int bufferLength = 0;
int count = 0;
int previousProgress = 0;
while ((bufferLength = inputStream.read(buffer)) > 0) {
if (this.isInterrupted()) {
throw new InterruptedException("Thread has been kill (Destroyed)");
}
fileOutput.write(buffer, 0, bufferLength);
count += bufferLength;
int progress = (int) (count * 100L / (float) fileSize);
if (previousProgress > 999) {
updateProgress(map.insertedCount, i, progress, download.Name);
notificationManager.notify(notificationId, mBuilder.build());
previousProgress = 0;
}
previousProgress++;
}
fileOutput.close();
} catch (IOException e) {
Log.e("IOException", "" + e.getMessage());
i++;
map.remove(data.getKey());
continue;
}
File actualFile = new File(uepFolder + "/" + download.FileName + "" + download.Format);
file.renameTo(actualFile);
Log.e("Downloaded",""+actualFile.getAbsoluteFile());
} catch (InterruptedException | InternetDisconnectedException e) {
throw e;
}
i++;
map.remove(data.getKey());
Log.e("Downloaded", "Remaining files are "+map.size());
}
Log.e("WhileCheck", "While End");
// Due to thread, sometime the sequence of code flow is not in correct flow, and "Download complete" Notifaction is getting shown
// Hence this check is required.
if (this.isInterrupted()) {
throw new InterruptedException("Thread has been kill (Destroyed)");
}
notificationManager.cancel(notificationId);
mBuilderComplete = new NotificationCompat.Builder(DownloadService.this, "default");
initChannels(DownloadService.this);
mBuilderComplete.setOngoing(false)
.setContentTitle("Download Complete")
.setColor(Color.WHITE)
.setSmallIcon(R.drawable.download);
notificationManager.notify(2, mBuilderComplete.build());
Log.e("DownloadingService", "File downloaded successfully");
stopSelf();
map.insertedCount = 0;
} catch (InterruptedException e) {
closeNotification();
Log.e("InterruptedException", "" + e.getMessage());
} catch (InternetDisconnectedException e) {
stopSelf();
closeNotification();
showNotification("Internet disconnected", "Download failed. Try again later.");
Log.e("InternetDisconnect", "" + e.getMessage());
}
}
private void updateProgress(int totalFiles, int currentFileCount, int currentProgress, String fileName) {
remoteViewsSmall.setTextViewText(R.id.tvOverAll, currentFileCount + "/" + totalFiles);
remoteViewsSmall.setProgressBar(R.id.overallProgress, totalFiles, currentFileCount, false);
remoteViewsBig.setTextViewText(R.id.tvOverAll, currentFileCount + "/" + totalFiles);
remoteViewsBig.setTextViewText(R.id.tvFileName, "Downloading " + fileName);
remoteViewsBig.setTextViewText(R.id.tvCurrentProgress, currentProgress + "%");
remoteViewsBig.setProgressBar(R.id.overallProgress, totalFiles, currentFileCount, false);
remoteViewsBig.setProgressBar(R.id.currentProgress, 100, currentProgress, false);
}
public void closeNotification() {
if (notificationManager != null)
notificationManager.cancel(notificationId);
}
public void showNotification(String title, String message) {
downloadFailBuilder = new NotificationCompat.Builder(DownloadService.this, "default");
initChannels(DownloadService.this);
downloadFailBuilder.setOngoing(false)
.setContentTitle(title)
.setContentText(message)
.setColor(Color.WHITE)
.setSmallIcon(android.R.drawable.stat_sys_warning);
notificationManager.notify(3, downloadFailBuilder.build());
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
ArrayList<Downloadables> list = (ArrayList<Downloadables>) intent.getSerializableExtra("downloadList");
for (Downloadables d : list) {
String key = d.Name + "" + d.FileName;
map.put(key, d);
}
if (thread == null || !thread.isAlive()) {
thread = new BackgroundThread(startId, map);
receiver = new DownloadCancelReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
intentFilter.addAction("CANCEL_DOWNLOAD");
registerReceiver(receiver, intentFilter);
thread.start();
}
}
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
Log.e("Service", " Stop");
try {
thread.interrupt();
} catch (Exception e) {
Log.e("Exception", "" + e.getMessage());
}
map.clear();
unregisterReceiver(receiver);
//closeNotification();
}
public static class DownloadCancelReceiver extends BroadcastReceiver {
public DownloadCancelReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase("CANCEL_DOWNLOAD")) {
Intent intent1 = new Intent(context, DownloadService.class);
context.stopService(intent1);
}
}
}
public void initChannels(Context context) {
if (Build.VERSION.SDK_INT < 26) {
return;
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel("default", "Channel name", NotificationManager.IMPORTANCE_LOW);
channel.setDescription("Channel description");
channel.setImportance(NotificationManager.IMPORTANCE_LOW);
channel.setSound(null, null);
notificationManager.createNotificationChannel(channel);
}
private class InternetDisconnectedException extends Exception {
public InternetDisconnectedException(String message) {
super(message);
}
}
public static class DownloadMap<String, Downloadables> extends HashMap<String, Downloadables> {
public int insertedCount;
#Override
public Downloadables put(String key, Downloadables value) {
insertedCount++;
return super.put(key, value);
}
}
}
And From activity I start service like this.
ArrayList<Downloadables> list = helper.GetVideoFileList();
Intent intent1 = new Intent(SRDownloadActivity.this, DownloadService.class);
intent1.putExtra("downloadList", list);
startService(intent1);
I can even Add files to HashMap while downloading is in progress. It also worked fine.
I am unable to figure it out why it is not running in background since it is on different thread.
Here is my notification look like
Threads are killed by the Android OS even if the main app is still working and they dont have access to the UI thats why u should use AsyncTask class its a like a thread that works in background but it has access to the UI of the main. And the jobdispatcher class can help u assign jobs in the background
Here is a good tutorial https://youtu.be/das7FmQIGik
i have created an Application for Nougat device where my application is detecting all the images taking by camera and i am sending this images in the server. My application is successfully sending the first photo taken by the camera but the receiver neither detecting the second image i am taking nor sending it to the server. I have a ConfigurationBuilder class which will trigger each and every 30 minutes to detect the new pictures by the camera and a cameraReceiver and a service class where i have registered the receiver.
ConfigurationBuilder.java
public class ConfigurationBuilder extends JobService {
JobParameters mRunningParams;
static final int PROJECTION_ID = 0;
static final int PROJECTION_DATA = 1;
static final String DCIM_DIR = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM).getPath();
static final String[] PROJECTION = new String[] {
MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA
};
static final List<String> EXTERNAL_PATH_SEGMENTS
= MediaStore.Images.Media.EXTERNAL_CONTENT_URI.getPathSegments();
String TAG = "JobService";
private Context mContext;
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public boolean onStartJob(JobParameters jobParameters) {
mContext = getApplicationContext();
getSettingResponse(true);
jobFinished(jobParameters, false);
Log.d(TAG, "onStartJob: ");
return true;
}
private void getSettingResponse(boolean fromJobScheduler) {
try {
if (fromJobScheduler)
new DataClear();
OkHttpClient client = new SSLManager().getClientKeyNonDeprecated(mContext);
// code request code here
HttpUrl.Builder urlBuilder =
HttpUrl.parse(mContext.getSharedPreferences(NetworkAPI.PREFNAME,Context.MODE_PRIVATE ).getString("configuration_url", "")).newBuilder();
//urlBuilder.addQueryParameter("device", CommonMethods.getBluetoothName());
urlBuilder.addQueryParameter("device", "FranksS7");
urlBuilder.addQueryParameter("membership", "Phone Network");
urlBuilder.addQueryParameter("membershipType", "Domain");
Request request = new Request.Builder().addHeader("Accept", "application/json")
.url(urlBuilder.build()).get()
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
getConfigure(null);
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
Log.d(TAG, "onResponse:Unexpected code" + response.body().string());
} else {
getConfigure(response.body().string());
}
}
});
} catch (Exception e) {
Log.d(TAG, "getSettingResponse: " + e.getMessage());
}
}
#Override
public boolean onStopJob(JobParameters jobParameters) {
return false;
}
private void getConfigure(String response) {
try {
if (response != null) {
JSONArray policies = new JSONObject(response).getJSONArray("Policies");
for (int i = 0; i < policies.length(); i++) {
JSONObject obj = policies.getJSONObject(i);
Iterator iterator = obj.keys();
String key = (String) iterator.next();
JSONObject issue = obj.getJSONObject(key);
String value = issue.optString("Value");
RecorderPolicies policiesField = new Select()
.from(RecorderPolicies.class)
.where("Policy = ?", key).executeSingle();
if (policiesField != null) {
policiesField.Value = value;
long res = policiesField.save();
// new Update(RecorderPolicies.class).set("Value = ?",value).where("Policy = ?", key).execute();
} else {
RecorderPolicies recorderPolicies = new RecorderPolicies();
recorderPolicies.Policy = key;
recorderPolicies.Value = value;
long res = recorderPolicies.save();
}
}
}
if (isMyServiceRunning(ApplicationService.class)) {
// stopService(new Intent(mContext, ApplicationService.class));
Log.d(TAG, "Service Terminated");
}
if (new RecorderPolicies().getActivateCode("CanRecordDetailedData"))
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
mContext.startService(new Intent(mContext, ApplicationService.class));
Log.d(TAG, "Service Restarted");
}
}, 10000);
else
Log.d(TAG, "----------------------problem starting service---------------------");
} catch (Exception e) {
Log.d(TAG, "getConfigure: " + e.getMessage());
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
public void startConfigurationScheduler(int JobID, Context activityContext) {
mContext = activityContext;
ComponentName jobService =
new ComponentName(activityContext, ConfigurationBuilder.class.getName());
JobInfo jobInfo =
new JobInfo.Builder(JobID, jobService)
.setPersisted(true).setRequiresDeviceIdle(true)
//updated code for nougat...............................................................on 12/11/2017
//.setPeriodic(32*60000, (long) (1.6*60000)).build();
.setPeriodic(32 * 60000).build();
JobScheduler jobScheduler = (JobScheduler) activityContext.getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);
getSettingResponse(false);
}
public void stopConfigurationScheduler(int JobID, Context activityContext) {
JobScheduler jobScheduler = (JobScheduler) activityContext.getSystemService(JOB_SCHEDULER_SERVICE);
jobScheduler.cancel(JobID);
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
Process.killProcess(service.pid); // kill service
return true;
}
}
return false;
}
}
CameraReceiver .java
public class CameraReceiver extends BroadcastReceiver {
private String pathSplit;
private String type;
Context mContext;
#Override
public void onReceive(Context context, Intent intent) {
mContext=context;
Cursor cursor = context.getContentResolver().query(intent.getData(),
null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
String image_path = cursor.getString(cursor.getColumnIndex("_data"));
String MediaType = intent.getAction().equals("android.hardware.action.NEW_VIDEO") ? "VIDEO" : "IMAGE";
FilesObservers.postDataCreateEvent("CREATE", image_path, true,MediaType);
cursor.close();
}
}
public IntentFilter getVideoFilters() {
IntentFilter lsIntentFilter = new IntentFilter();
try {
lsIntentFilter.addDataType("video/*");
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
lsIntentFilter.addAction("android.hardware.action.NEW_VIDEO");
lsIntentFilter.addCategory("android.intent.category.DEFAULT");
return lsIntentFilter;
}
public IntentFilter getCameraFilters() {
IntentFilter lsIntentFilter = new IntentFilter();
try {
lsIntentFilter.addDataType("image/*");
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
} //lsIntentFilter.addAction("JobInfo.Builder.addTriggerContentUri(JobInfo.TriggerContentUri)");
lsIntentFilter.addAction("android.provider.MediaStore.ACTION_IMAGE_CAPTURE)");
lsIntentFilter.addCategory("android.intent.category.DEFAULT");
return lsIntentFilter;
}
}
In Nougat ACTION_NEW_VIDEO and ACTION_NEW_PICTURE broadcasts were removed.
Instead this they recommend to use JobInfo.Builder.JobInfo.Builder.addTriggerContentUri(JobInfo.TriggerContentUri)
It is funny because In Android O this broadcast has been brought back - for registered receivers only.
I am trying add one thing in my app. What i am trying is whenever user get phone call or user make phone call, at same time recording should be start and recording must store in sd card after cutting the call.
Issues
1)Incoming call record work sometimes
2)Outgoing not working
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 0;
private DevicePolicyManager mDPM;
private ComponentName mAdminName;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PackageManager p = getPackageManager();
p.setComponentEnabledSetting(getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
try {
// Initiate DevicePolicyManager.
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mAdminName = new ComponentName(this, DeviceAdminDemo.class);
if (!mDPM.isAdminActive(mAdminName)) {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "Click on Activate button to secure your application.");
startActivityForResult(intent, REQUEST_CODE);
} else {
// mDPM.lockNow();
// Intent intent = new Intent(MainActivity.this,
// TrackDeviceService.class);
// startService(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (REQUEST_CODE == requestCode) {
Intent intent = new Intent(MainActivity.this, TService.class);
startService(intent);
}
}
}
TService
public class TService extends Service {
MediaRecorder recorder;
File audiofile;
String name, phonenumber;
String audio_format;
public String Audio_Type;
int audioSource;
Context context;
Timer timer;
Boolean offHook = false, ringing = false;
Toast toast;
Boolean isOffHook = false;
private boolean recordstarted = false;
private static final String ACTION_IN = "android.intent.action.PHONE_STATE";
private static final String ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL";
private CallBr br_call;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
Log.d("service", "destroy");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// final String terminate =(String)
// intent.getExtras().get("terminate");//
// intent.getStringExtra("terminate");
// Log.d("TAG", "service started");
//
// TelephonyManager telephony = (TelephonyManager)
// getSystemService(Context.TELEPHONY_SERVICE); // TelephonyManager
// // object
// CustomPhoneStateListener customPhoneListener = new
// CustomPhoneStateListener();
// telephony.listen(customPhoneListener,
// PhoneStateListener.LISTEN_CALL_STATE);
// context = getApplicationContext();
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_OUT);
filter.addAction(ACTION_IN);
this.br_call = new CallBr();
this.registerReceiver(this.br_call, filter);
// if(terminate != null) {
// stopSelf();
// }
return START_NOT_STICKY;
}
public class CallBr extends BroadcastReceiver {
Bundle bundle;
String state;
String inCall, outCall;
public boolean wasRinging = false;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_IN)) {
if ((bundle = intent.getExtras()) != null) {
state = bundle.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
wasRinging = true;
Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();
} else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
if (wasRinging == true) {
Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
String out = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss").format(new Date());
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/TestRecordingDasa1");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
String file_name = "Record";
try {
audiofile = File.createTempFile(file_name, ".amr", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
System.out.println("PATH"+path);
recorder = new MediaRecorder();
// recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
recordstarted = true;
}
} else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
wasRinging = false;
Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
if (recordstarted) {
recorder.stop();
recordstarted = false;
}
}
}
} else if (intent.getAction().equals(ACTION_OUT)) {
if ((bundle = intent.getExtras()) != null) {
outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
}
}
}
}
}
Remove this if (wasRinging == true) from TService, this wasRining Boolean checks if the phone was ringing some time before, i.e. when phone receives a call, in case of outgoing call it stays false so, the recorder part is skipped. Just change that and it should work.
Just replace your TService code with this..
public class TService extends Service {
MediaRecorder recorder;
File audiofile;
String name, phonenumber;
String audio_format;
public String Audio_Type;
int audioSource;
Context context;
Timer timer;
Boolean offHook = false, ringing = false;
Toast toast;
Boolean isOffHook = false;
private boolean recordstarted = false;
private static final String ACTION_IN = "android.intent.action.PHONE_STATE";
private static final String ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL";
private CallBr br_call;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
Log.d("service", "destroy");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// final String terminate =(String)
// intent.getExtras().get("terminate");//
// intent.getStringExtra("terminate");
// Log.d("TAG", "service started");
//
// TelephonyManager telephony = (TelephonyManager)
// getSystemService(Context.TELEPHONY_SERVICE); // TelephonyManager
// // object
// CustomPhoneStateListener customPhoneListener = new
// CustomPhoneStateListener();
// telephony.listen(customPhoneListener,
// PhoneStateListener.LISTEN_CALL_STATE);
// context = getApplicationContext();
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_OUT);
filter.addAction(ACTION_IN);
this.br_call = new CallBr();
this.registerReceiver(this.br_call, filter);
// if(terminate != null) {
// stopSelf();
// }
return START_NOT_STICKY;
}
public class CallBr extends BroadcastReceiver {
Bundle bundle;
String state;
String inCall, outCall;
public boolean wasRinging = false;
public boolean didMakeACall = false;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_IN)) {
if ((bundle = intent.getExtras()) != null) {
state = bundle.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
wasRinging = true;
Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();
} else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
if (wasRinging || didMakeACall) {
Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
String out = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss").format(new Date());
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/TestRecordingDasa1");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
String file_name = "Record";
try {
audiofile = File.createTempFile(file_name, ".amr", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
System.out.println("PATH"+path);
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
recordstarted = true;
}
} else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
wasRinging = false;
Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
if (recordstarted) {
recorder.stop();
recordstarted = false;
}
}
}
} else if (intent.getAction().equals(ACTION_OUT)) {
if ((bundle = intent.getExtras()) != null) {
didMakeACall = true;
outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
}
}
}
}
}
I'm afraid community wouldn't like external links here so I'm posting my quick demo project here...
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".TService"/>
</application>
MainActivity.java
I'm starting TService in its onCreate method, please note that this could be any activity in your project, or any context you can start a service from.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, TService.class));
}
}
and now finally,
TService.java
I've tested this in Kitkat and Lollipop and it's working, for newer versions you need to explicitly ask for Manifest permissions during run time and it should work just as fine.
public class TService extends Service {
MediaRecorder recorder;
File audiofile;
String name, phonenumber;
String audio_format;
public String Audio_Type;
int audioSource;
Context context;
Timer timer;
Boolean offHook = false, ringing = false;
Toast toast;
Boolean isOffHook = false;
private boolean recordstarted = false;
private static final String ACTION_IN = "android.intent.action.PHONE_STATE";
private static final String ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL";
private CallBr br_call;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onDestroy() {
Log.d("service", "destroy");
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// final String terminate =(String)
// intent.getExtras().get("terminate");//
// intent.getStringExtra("terminate");
// Log.d("TAG", "service started");
//
// TelephonyManager telephony = (TelephonyManager)
// getSystemService(Context.TELEPHONY_SERVICE); // TelephonyManager
// // object
// CustomPhoneStateListener customPhoneListener = new
// CustomPhoneStateListener();
// telephony.listen(customPhoneListener,
// PhoneStateListener.LISTEN_CALL_STATE);
// context = getApplicationContext();
final IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_OUT);
filter.addAction(ACTION_IN);
this.br_call = new CallBr();
this.registerReceiver(this.br_call, filter);
// if(terminate != null) {
// stopSelf();
// }
return START_NOT_STICKY;
}
public class CallBr extends BroadcastReceiver {
Bundle bundle;
String state;
String inCall, outCall;
public boolean wasRinging = false;
boolean didMakeACall = false;
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_IN)) {
if ((bundle = intent.getExtras()) != null) {
state = bundle.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
wasRinging = true;
Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();
} else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
if (wasRinging || didMakeACall) {
Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();
String out = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss").format(new Date());
File sampleDir = new File(Environment.getExternalStorageDirectory(), "/MyRecorder");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
String file_name = "Record";
try {
audiofile = File.createTempFile(file_name, ".amr", sampleDir);
} catch (IOException e) {
e.printStackTrace();
}
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
System.out.println("PATH"+path);
recorder = new MediaRecorder();
// recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(audiofile.getAbsolutePath());
try {
recorder.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
recorder.start();
recordstarted = true;
}
} else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
wasRinging = false;
Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
if (recordstarted) {
recorder.stop();
recordstarted = false;
}
}
}
} else if (intent.getAction().equals(ACTION_OUT)) {
if ((bundle = intent.getExtras()) != null) {
didMakeACall = true;
outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
}
}
}
}
}
My application should take pictures in background at a specific time of the day. I am going to use AlarmManager but I am wondering whether the class which implements the behavior of my application (i.e., taking a picture) should extend Service or BroadcastReceiver. What do you think?
You should use IntentSerivce with AlaramManger and define the BroadcastReceiver on your activity.
public class DownloadService extends IntentService {
private int result = Activity.RESULT_CANCELED;
public static final String URL = "urlpath";
public static final String FILENAME = "filename";
public static final String FILEPATH = "filepath";
public static final String RESULT = "result";
public static final String NOTIFICATION = "com.vogella.android.service.receiver";
public DownloadService() {
super("DownloadService");
}
// Will be called asynchronously be Android
#Override
protected void onHandleIntent(Intent intent) {
String urlPath = intent.getStringExtra(URL);
String fileName = intent.getStringExtra(FILENAME);
File output = new File(Environment.getExternalStorageDirectory(),
fileName);
if (output.exists()) {
output.delete();
}
InputStream stream = null;
FileOutputStream fos = null;
try {
URL url = new URL(urlPath);
stream = url.openConnection().getInputStream();
InputStreamReader reader = new InputStreamReader(stream);
fos = new FileOutputStream(output.getPath());
int next = -1;
while ((next = reader.read()) != -1) {
fos.write(next);
}
// Successful finished
result = Activity.RESULT_OK;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
publishResults(output.getAbsolutePath(), result);
}
private void publishResults(String outputPath, int result) {
Intent intent = new Intent(NOTIFICATION);
intent.putExtra(FILEPATH, outputPath);
intent.putExtra(RESULT, result);
sendBroadcast(intent);
}
}
public class MainActivity extends Activity {
private TextView textView;
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
String string = bundle.getString(DownloadService.FILEPATH);
int resultCode = bundle.getInt(DownloadService.RESULT);
if (resultCode == RESULT_OK) {
Toast.makeText(MainActivity.this,
"Download complete. Download URI: " + string,
Toast.LENGTH_LONG).show();
textView.setText("Download done");
} else {
Toast.makeText(MainActivity.this, "Download failed",
Toast.LENGTH_LONG).show();
textView.setText("Download failed");
}
}
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.status);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, new IntentFilter(DownloadService.NOTIFICATION));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
public void onClick(View view) {
Intent intent = new Intent(this, DownloadService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
// Start every 30 seconds
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30*1000, pintent);
}
}
I'm making an app that sends a notification to the status bar, it sends the notification when stepping through the code in the debugger, however it never sends the notification when run in realtime.
Here is my runnable that generates the notification, again when stepping through this code in the debugger the notification runs however in realtime nothing happens.
public class NewsEvents_Service extends Service {
private static final String NEWSEVENTS = "newsevents";
private static final String KEYWORDS = "keywords";
private NotificationManager mNM;
private ArrayList<NewsEvent> neList;
private int count;
#Override
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
neList = new ArrayList<NewsEvent>();
getKeywords();
//getNewsEvents();
Thread thr = new Thread(null, mTask, "NewsEvents_Service");
thr.start();
Log.d("Thread", "IT STARTED!!!!!!????!!!!!!!!!!!!!!!?!!?");
}
#Override
public void onDestroy() {
// Cancel the notification -- we use the same ID that we had used to start it
mNM.cancel(R.string.ECS);
// Tell the user we stopped.
Toast.makeText(this, "Service Done", Toast.LENGTH_SHORT).show();
}
/**
* The function that runs in our worker thread
*/
Runnable mTask = new Runnable() {
public void run() {
getNewsEventsFromWeb();
for(NewsEvent ne : neList){
Log.d("Thread Running", "Service Code running!!!!!!!!!!!!!!!");
String body = ne.getBody().replaceAll("\\<.*?>", "");
String title = ne.getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
ne.setInterested(true);
}
}
if(ne.isInterested() == true ){
Notification note = new Notification(R.drawable.icon,
"New ECS News Event", System.currentTimeMillis());
Intent i = new Intent(NewsEvents_Service.this, FullNewsEvent.class);
i.putExtra("ne", ne);
PendingIntent pi = PendingIntent.getActivity(NewsEvents_Service.this, 0,
i, 0);
note.setLatestEventInfo(NewsEvents_Service.this, "New Event", ne.getTitle(), pi);
note.flags = Notification.FLAG_AUTO_CANCEL;
mNM.notify(R.string.ECS, note);
}
}
}
};
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/**
* Show a notification while this service is running.
*/
private void getNewsEventsFromWeb() {
HttpClient client = new DefaultHttpClient();
HttpGet get;
try {
get = new HttpGet(getString(R.string.jsonnewsevents));
ResponseHandler<String> response = new BasicResponseHandler();
String responseBody = client.execute(get, response);
String page = responseBody;
Bundle data = new Bundle();
data.putString("page",page);
Message msg = new Message();
msg.setData(data);
handler.sendMessage(msg);
}
catch (Throwable t) {
Log.d("UpdateNews", "PROBLEMS");
}
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private ArrayList<String> keyWordList;
public void getNewsEvents(){
try {
InputStream fi = openFileInput(NEWSEVENTS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
neList = (ArrayList<NewsEvent>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(neList == null){
neList = new ArrayList<NewsEvent>();
}
}
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
/**
* This is the object that receives interactions from clients. See RemoteService
* for a more complete example.
*/
private final IBinder mBinder = new Binder() {
#Override
protected boolean onTransact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
return super.onTransact(code, data, reply, flags);
}
};
}
Here is my activity that schedules the service to run
public class NewsEvents extends ListActivity{
private URL JSONNewsEvents;
private ArrayList<NewsEvent> neList;
private ArrayList<String> keyWordList;
private Worker worker;
private NewsEvents ne;
public static final String KEYWORDS = "keywords";
private static final String NEWSEVENTS = "newsevents";
public static final int ONE_ID = Menu.FIRST+1;
private PendingIntent newsAlarm;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newsevents);
ne = this;
neList = new ArrayList<NewsEvent>();
try {
JSONNewsEvents = new URL(getString(R.string.jsonnewsevents));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
worker = new Worker(handler, this);
setListAdapter(new IconicAdapter());
getKeywords();
worker.execute(JSONNewsEvents);
}
#Override
protected void onStop() {
super.onStop();
writeNewsEvents() ;
}
#Override
protected void onPause(){
super.onPause();
writeNewsEvents();
}
private void writeNewsEvents() {
try {
OutputStream fi = openFileOutput(NEWSEVENTS, 0);
if (fi!=null) {
ObjectOutputStream out = new ObjectOutputStream(fi);
out.writeObject(neList);
out.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
}
/**
* #return
*/
public ArrayList<String> getKeywords(){
try {
InputStream fi = openFileInput(KEYWORDS);
if (fi!=null) {
ObjectInputStream in = new ObjectInputStream(fi);
keyWordList = (ArrayList<String>) in.readObject();
in.close();
}
}
catch (java.io.FileNotFoundException e) {
// that's OK, we probably haven't created it yet
}
catch (Throwable t) {
Toast
.makeText(this, "Exception: "+t.toString(), Toast.LENGTH_LONG)
.show();
}
if(keyWordList == null){
keyWordList = new ArrayList<String>();
return keyWordList;
}
return keyWordList;
}
public void onListItemClick(ListView parent, View v,
int position, long id) {
startFullNewsEvent(neList.get(position));
}
/**
* #param newsEvent
*/
public void startFullNewsEvent(NewsEvent ne) {
Intent intent = new Intent(this, FullNewsEvent.class);
intent.putExtra("ne", ne);
this.startActivity(intent);
finish();
}
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
String page = msg.getData().getString("page");
try {
JSONArray parseArray = new JSONArray(page);
for (int i = 0; i < parseArray.length(); i++) {
JSONObject jo = parseArray.getJSONObject(i);
String title = jo.getString("title");
String body =jo.getString("body");
String pd = jo.getString("postDate");
String id = jo.getString("id");
NewsEvent ne = new NewsEvent(title, pd , body, id);
boolean unique = true;
for(NewsEvent ne0 : neList){
if(ne.getId().equals(ne0.getId())){
unique = false;
}else{
unique = true;
}
}
if(unique == true){
neList.add(ne);
}
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ne.setListAdapter(new IconicAdapter());
}
};
public class IconicAdapter extends ArrayAdapter<NewsEvent> {
IconicAdapter() {
super(NewsEvents.this, R.layout.rownews, neList);
}
public View getView(int position, View convertView,ViewGroup parent) {
LayoutInflater inflater=getLayoutInflater();
View row=inflater.inflate(R.layout.rownews, parent, false);
TextView label=(TextView)row.findViewById(R.id.label);
ImageView image= (ImageView)row.findViewById(R.id.icon);
String body = neList.get(position).getBody();
body.replaceAll("\\<.*?>", "");
String title = neList.get(position).getTitle();
for(String s : keyWordList){
if(body.contains(s) || body.contains(s.toLowerCase()) ||
title.contains(s) || title.contains(s.toLowerCase())){
neList.get(position).setInterested(true);
}
}
if(neList.get(position).isInterested() == true){
image.setImageResource(R.drawable.star);
}
label.setText(neList.get(position).getTitle());
return(row);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
populateMenu(menu);
return(super.onCreateOptionsMenu(menu));
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return(applyMenuChoice(item) || super.onOptionsItemSelected(item));
}
//Creates our activity to menus
private void populateMenu(Menu menu) {
menu.add(Menu.NONE, ONE_ID, Menu.NONE, "Home");
}
private boolean applyMenuChoice(MenuItem item) {
switch (item.getItemId()) {
case ONE_ID: startHome(); return(true);
}
return(false);
}
public void startHome() {
Intent intent = new Intent(this, ECS.class);
this.startActivity(intent);
finish();
}
}
Race conditions, I'm making an HTTP Request and then handing it off to a handler, immediately following that I iterator through the array list, which at full speed is empty because the HTTP hasn't completed. In debugging it all slows down so the HTTP is complete and all works well.
Threads and Network Connections, a deadly combination.