In my MainActivity XML file, I have an EditText which id is editsearch. I have a service class for listening to the clipboard text and open my app. Everything is happening fine but I can't set the text to my editsearch when my app opens from service class.
findViewById method is not work in the onStartCommand method of my service. I have also tried defining my editsearch EditText as a static property in my MainActivity class but not getting my expected result.
Here is my service class
package com.learn24bd.ad;
import android.app.Service;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
public class MyServiceReceiver extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MySerivce","Service Started");
final ClipboardManager clipboard = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
public void onPrimaryClipChanged() {
String copiedText = clipboard.getText().toString();
Log.i("Copied",copiedText);
/* here i want to setText to my editsearch
also tried with static property
MainActivity.editsearch.setText(copiedText);
*/
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
});
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Services aren't suitable for dealing with UI.
Instead, in your case, you should pass the clipboard content for the MainActivity class to handle. For that, pass it as an intent extra:
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("clipboard_text", copiedText)
startActivity(i);
And receive and handle the text in your activity:
String clipboardText = getIntent().getStringExtra("clipboard_text");
Then you can set the text to your EditText:
editText.setText(clipboardText)
Related
I have a BroadcastReceiver class which gets trigged sometimes And I also have a Service class. My Service class starts from my Application class named G.class. I want my Service class to start before BroadcastReceiver class. but as I see in LogCat, First G.class starts and it ends then BroadcastReceiver class starts and it ends then Service class starts. What is the problem?
AlarmReceiver.class
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Intent;
import com.hadi.android.dm.app.Logger;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Logger.i("receiver started");
//do something
}
}
G.class
import android.content.Intent;
public class G extends Application {
#Override
public void onCreate() {
super.onCreate();
Logger.i("G started");
startService(new Intent(getApplicationContext(), ApplicationService.class));
Logger.i("G ended");
}
ApplicationService.class
import android.app.Service;
import android.content.Context;
import android.content.Intent;
public class ApplicationService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.i("service started");
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Logger.i("service ended");
}
}
How my BroadcastReciever gets trigged
public void schedule(long time) {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 2, new Intent(context, AlarmReceiver.class), 0);
android.app.AlarmManager alarmManager = (android.app.AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent);
} else {
alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent);
}
}
My LogCat
07-09 00:44:00.797 18172-18172/com.hadi.android.dm I/MYAPP: G started
07-09 00:44:00.886 18172-18172/com.hadi.android.dm I/MYAPP: G ended
07-09 00:44:00.888 18172-18172/com.hadi.android.dm I/MYAPP: receiver started
07-09 00:44:00.890 18172-18172/com.hadi.android.dm I/MYAPP: service started
There's no way to do this. Here's what's happening:
The alarm goes off
The app, which is not running, is started. The received broadcast is noted and an actuon to call the receiver put in the Handler on the main thread.
The app creates the Application class. This calls startService, which adds an action to create the service to the Handler on the main thread.
The main thread message loop is returned to. It takes the next message on the queue, the BR message, and runs it, starting the BroadcastReceiver.
The main thread message loop is returned to. It takes the next message on the queue, the SS message, and runs it, starting the Service.
There is no way to change the ordering in any of this.
I'm trying to create a timer that would launch in the background once onDestroy() is triggered, and once the timer reaches 6 hours, SharedPreferences will be used to make a change in the app.
I was wondering... what would be the correct way to setup CountDownTimer or anything similar it for onDestroy().
I will answer anything if needed. Thank you.
After about a week, a working answer came up. This answer includes what's related to how to make the service run. In this scenario, I'm building a CountDownTimer service.
AndroidManifest.xml
<service android:name=".TimeService"/>
MainActivity.java
import android.content.Intent;
import android.support.v4.content.ContextCompat;
public class MainActivity extends AppCompatActivity {
Intent i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
i = new Intent(this, TimeService.class);
stopService(i); //To stop the service the next time the app is launched.
}
#Override
protected void onDestroy() {
launchService(); //Launches the service once when app shuts down.
super.onDestroy();
}
public void launchService() { //How to launch the service, depending the phone's API.
if(Build.VERSION.SDK_INT >= 26) {
startForegroundService(new Intent(this, TimeService.class));
}
else{
Intent i;
i = new Intent(this, TimeService.class);
ContextCompat.startForegroundService(this, i);
}
}
}
TimeService.java
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.CountDownTimer;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class TimeService extends Service {
CountDownTimer cdt = null;
private SharedPreferences pref;
//Things you want SharedPreferences to change.
Intent i;
#Override
public void onCreate() {
i = new Intent(this, TimeService.class);
startService(i);
pref = this.getSharedPreferences("myAppPref", MODE_PRIVATE);
cdt = new CountDownTimer(3600000, 1000) { //One hour timer with one second interval.
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
//Whatever you need SharedPreferences to change here.
}
};
cdt.start();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I've been able to successfully create an app (thanks davidgyoung!) that monitors beacons in the background and then subsequently opens the app in the background.
Now I would like my app to first prompt with a notification in the status bar saying something like "I've detected a beacon! Would you like to open out app?". Then the user would click on the notification to open the app or dismiss it and ignore the notification.
I've searched on stack overflow for something like but haven't had much success in finding something relevant to beacons. I did find this page that talks about adding StatusBar notifications but I'm not having much success.
Particularly its in my BeaconReferenceApplication.java and MonitoringActivity.java file. I think I put the code in the correct place (after didEnterRegion) but I have unresolved classes for areas like notificationButton, setLatestEventInfo, etc. Can someone help? Thanks in advance!
BeaconReferenceApplication.java:
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
public class BeaconReferenceApplication extends Application implements BootstrapNotifier {
private static final String TAG = "BeaconReferenceApp";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private MonitoringActivity monitoringActivity = null;
public void onCreate() {
super.onCreate();
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb. To find the proper
// layout expression for other beacon types, do a web search for "setBeaconLayout"
// including the quotes.
//
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
Log.d(TAG, "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
Region region = new Region("backgroundRegion", Identifier.parse("2F234454F4911BA9FFA6"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
// simply constructing this class and holding a reference to it in your custom Application
// class will automatically cause the BeaconLibrary to save battery whenever the application
// is not visible. This reduces bluetooth power usage by about 60%
backgroundPowerSaver = new BackgroundPowerSaver(this);
// If you wish to test beacon detection in the Android Emulator, you can use code like this:
// BeaconManager.setBeaconSimulator(new TimedBeaconSimulator() );
// ((TimedBeaconSimulator) BeaconManager.getBeaconSimulator()).createTimedSimulatedBeacons();
}
#Override
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever a Beacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedBeaconsSinceBoot) {
Log.d(TAG, "sending notification to StatusBar");
#SuppressWarnings("deprecation")
private void Notify(String notificationTitle, String notificationMessage) {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
#SuppressWarnings("deprecation")
Notification notification = new Notification(R.mipmap.ic_launcher,
"New Message", System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MonitoringActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(MonitoringActivity.this, notificationTitle,
notificationMessage, pendingIntent);
notificationManager.notify(9999, notification);
}
}
} else {
if (monitoringActivity != null) {
Log.d(TAG, "auto launching MainActivity");
// The very first time since boot that we detect an beacon, we launch the
// MainActivity
Intent intent = new Intent(this, MonitoringActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Important: make sure to add android:launchMode="singleInstance" in the manifest
// to keep multiple copies of this activity from getting created if the user has
// already manually launched the app.
this.startActivity(intent);
haveDetectedBeaconsSinceBoot = true;
}
}
}
#Override
public void didExitRegion(Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I no longer see a beacon.");
}
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I have just switched from seeing/not seeing beacons: " + state);
}
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("An beacon is nearby.")
.setSmallIcon(R.mipmap.ic_launcher);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, MonitoringActivity.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(MonitoringActivity activity) {
this.monitoringActivity = activity;
}
}
MonitoringActivity.java:
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import org.altbeacon.beacon.BeaconManager;
public class MonitoringActivity extends Activity {
protected static final String TAG = "MonitoringActivity";
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
private WebView mWebView;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monitoring);
// code for button notification
Button notificationButton = (Button) findViewById(R.id.notificationButton);
notificationButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Notify("Title: Meeting with Business",
"Msg:Pittsburg 10:00 AM EST ");
}
});
// code for button notification
mWebView = (WebView) findViewById(R.id.activity_main_webview);
progressBar = (ProgressBar) findViewById(R.id.progressBar1);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
mWebView.loadUrl("http://communionchapelefca.org/edy-home");
mWebView.setWebViewClient(new MyAppWebViewClient());
verifyBluetooth();
Log.d(TAG, "Application just launched");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android M Permission check
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect beacons in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#TargetApi(23)
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}
}
}
private class HelloWebViewClient extends WebViewClient{
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
super.onPageStarted(view, url, favicon);
}
#Override
public boolean shouldOverrideUrlLoading(WebView webView, String url)
{
webView.loadUrl(url);
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
progressBar.setVisibility(view.GONE);
}
}
#Override
public void onBackPressed() {
if(mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
public void onRangingClicked(View view) {
Intent myIntent = new Intent(this, RangingActivity.class);
this.startActivity(myIntent);
}
#Override
public void onResume() {
super.onResume();
((BeaconReferenceApplication) this.getApplicationContext()).setMonitoringActivity(this);
}
#Override
public void onPause() {
super.onPause();
((BeaconReferenceApplication) this.getApplicationContext()).setMonitoringActivity(null);
}
private void verifyBluetooth() {
try {
if (!BeaconManager.getInstanceForApplication(this).checkAvailability()) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth not enabled");
builder.setMessage("Please enable bluetooth in settings and restart this application.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
catch (RuntimeException e) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Bluetooth LE not available");
builder.setMessage("Sorry, this device does not support Bluetooth LE.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
finish();
System.exit(0);
}
});
builder.show();
}
}
}
So I was able to fix my problem by using the example from the Android Developers website for Notifications. I used their sample code, adapted it to my use, and then even further used .bigText to make my notification look great. Credit goes to them and daviggyoung for getting my app working. Thanks!
I also didnt need to edit my MonitoringActivity.java like I posted earlier.
final BeaconReferenceApplication.java:
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.Region;
import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
import org.altbeacon.beacon.startup.RegionBootstrap;
import org.altbeacon.beacon.startup.BootstrapNotifier;
public class BeaconReferenceApplication extends Application implements BootstrapNotifier {
private static final String TAG = "BeaconReferenceApp";
private RegionBootstrap regionBootstrap;
private BackgroundPowerSaver backgroundPowerSaver;
private boolean haveDetectedBeaconsSinceBoot = false;
private MonitoringActivity monitoringActivity = null;
public void onCreate() {
super.onCreate();
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it
// find a different type of beacon, you must specify the byte layout for that beacon's
// advertisement with a line like below. The example shows how to find a beacon with the
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb. To find the proper
// layout expression for other beacon types, do a web search for "setBeaconLayout"
// including the quotes.
//
beaconManager.getBeaconParsers().clear();
beaconManager.getBeaconParsers().add(new BeaconParser().
setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
Log.d(TAG, "setting up background monitoring for beacons and power saving");
// wake up the app when a beacon is seen
Region region = new Region("backgroundRegion", Identifier.parse("2F234454F4911BA9FFA6"), null, null);
regionBootstrap = new RegionBootstrap(this, region);
// simply constructing this class and holding a reference to it in your custom Application
// class will automatically cause the BeaconLibrary to save battery whenever the application
// is not visible. This reduces bluetooth power usage by about 60%
backgroundPowerSaver = new BackgroundPowerSaver(this);
// If you wish to test beacon detection in the Android Emulator, you can use code like this:
// BeaconManager.setBeaconSimulator(new TimedBeaconSimulator() );
// ((TimedBeaconSimulator) BeaconManager.getBeaconSimulator()).createTimedSimulatedBeacons();
}
#Override
public void didEnterRegion(Region arg0) {
// In this example, this class sends a notification to the user whenever a Beacon
// matching a Region (defined above) are first seen.
Log.d(TAG, "did enter region.");
if (!haveDetectedBeaconsSinceBoot) {
Log.d(TAG, "sending notification to StatusBar");
//begin code for notification
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("Message from Communion Chapel")
.setContentText("Welcome! Thanks for coming!")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText("We noticed that you're here today, click here to open the app and get today's Sermon Notes and Bulletin."))
.setAutoCancel(true);
;
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, MonitoringActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MonitoringActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(123, mBuilder.build());
}
}
#Override
public void didExitRegion(Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I no longer see a beacon.");
}
}
#Override
public void didDetermineStateForRegion(int state, Region region) {
if (monitoringActivity != null) {
Log.d(TAG,"I have just switched from seeing/not seeing beacons: " + state);
}
}
private void sendNotification() {
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this)
.setContentTitle("Beacon Reference Application")
.setContentText("A beacon is nearby.")
.setSmallIcon(R.drawable.app_icon);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(new Intent(this, MonitoringActivity.class));
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
builder.setContentIntent(resultPendingIntent);
NotificationManager notificationManager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void setMonitoringActivity(MonitoringActivity activity) {
this.monitoringActivity = activity;
}
}
There is a strange behaviour of assigning/modifying instance variable of the class inside Button OnClick() handlers.
As shown below, the instance variable "CurrentFile" is modified inside imgBtn.setOnClickListener() handlers. But when this variable is accessed in onActivityResult() method, this variable contains the value "null".
According to my understanding, the activity "GetPicActivity" will not be destroyed till the Camera activity returns. So, the instance variable "CurrentFile" should not be null.
Please help, if I am missing some basics.
import java.io.File;
import java.io.IOException;
import com.favoritepics.R;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.Toast;
public class GetPicActivity extends Activity {
protected static final int ID_REQ_IMAGE_CAPTURE = 1;
protected static final int ID_REQ_PICK_PHOTO = 0;
protected File currentFile = null; /// Goal is "to modify this variable inside Button onClick handlers"
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setBackgroundDrawable(
new ColorDrawable(android.graphics.Color.DKGRAY));
setContentView(R.layout.activity_get_pic);
// set handler image gallery
ImageButton imgBtn = (ImageButton) findViewById(R.id.imgGallery);
imgBtn.setOnClickListener(new ImageButton.OnClickListener() {
#Override
public void onClick(View v) {
// create intent to take picture on camera
Intent pickPhoto = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto, ID_REQ_PICK_PHOTO);
}
});
// set handler for camera image
imgBtn = (ImageButton) findViewById(R.id.imgCamera);
imgBtn.setOnClickListener(new ImageButton.OnClickListener() {
#Override
public void onClick(View v) {
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File tempDir = Environment.getExternalStorageDirectory();
File tempFile = null;
try {
currentFile = File
.createTempFile("_jpeg_", ".jpg", tempDir);
} catch (IOException exception) {
Toast.makeText(
GetPicActivity.this,
"Problem occured during creation of temp file! "
+ exception.getMessage(),
Toast.LENGTH_SHORT).show();
}
if (currentFile != null) {
takePicture.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(currentFile));
startActivityForResult(takePicture, ID_REQ_IMAGE_CAPTURE);
}
}
});
// set handler for cancel button
Button btnCancel = (Button) findViewById(R.id.btnCancel);
btnCancel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case ID_REQ_IMAGE_CAPTURE:
if (resultCode == RESULT_OK) {
Intent newIntent = new Intent();
newIntent.putExtra("TYPE", requestCode);
newIntent.putExtra("PATH", currentFile.getAbsolutePath());
setResult(RESULT_OK, newIntent);
finish();
}
break;
default:
break;
}
}
}
click here to see Logcat messages
Steps what I intend to do:
1, Create a temporary file in External storage for the destination of Camera picture
2, Start Camera to take a picture by passing the URI of temporary file
3, OnActivityResult() from camera, return the (temporary) File path to previous activity for further process
But here what I see is,
As soon as the Camera is started & picture is taken, the GetPicActivity is created again. Because of this, the instance variable "CurrentFile" will be null & in OnActivityResult() , I could not get the File path of temporary file.
Why is the GetPicActivity destroyed after starting Camera?
When the camera is started, the Camera appears in the screen orientation "Landscape".
Even the orientation of already existing activity stack is changed to "Landscape" itseems.
So, When the result of Camera is returned to GetPicActivity method OnActivityResult(), the GetPicActivity is created again. But now, the instance variable "CurrentFile" is null. This, gives a NullPointerException.
Recently I have been interested in Android Development and a friend gave me the book "Android Application Development for Dummies". In the book, there is a example app entitled Silent Toggle Mode. Later on there it teaches you to make a home screen widget for the app. I have typed in everything from the book exactly but it still gives me an error notifying me that the onReceive() method is never called. Here is the code:
package com.example.myapplication;
import android.app.Activity;
import android.app.IntentService;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.widget.RemoteViews;
public class AppWidget extends AppWidgetProvider {
#Override
public void onRecieve(Context context, Intent intent) {
if(intent.getAction()==null) {
context.startService(new Intent(context, ToggleService.class));
} else {
super.onReceive(context, intent);
}
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
context.startService(new Intent(context, ToggleService.class));
}
public static class ToggleService extends IntentService {
public ToggleService() {
super("AppWidget$ToggleService");
}
#Override
protected void onHandleIntent(Intent intent) {
ComponentName me=new ComponentName(this, AppWidget.class);
AppWidgetManager mgr=AppWidgetManager.getInstance(this);
mgr.updateAppWidget(me, buildUpdate(this));
}
private RemoteViews buildUpdate(Context context) {
RemoteViews updateViews=new RemoteViews(context.getPackageName(),R.layout.widget);
AudioManager audioManager=(AudioManager)context.getSystemService(Activity.AUDIO_SERVICE);
if(audioManager.getRingerMode()==AudioManager.RINGER_MODE_SILENT) {
updateViews.setImageViewResource(R.id.phoneState,R.drawable.phone_state_normal);
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
} else {
updateViews.setImageViewResource(R.id.phoneState,R.drawable.phone_state_silent);
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
Intent i=new Intent(this, AppWidget.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
updateViews.setOnClickPendingIntent(R.id.phoneState, pi);
return updateViews;
}
}
}
You have a typo, it's onReceive() and not onRecieve(). Write it like this:
public void onReceive(Context context, Intent intent)
This is a good example of why we should always use the #Override annotation, it simplifies finding bugs such as this one.