I have android app as I call html files one of these files page for play sound as user can
manage when the sound play as:
Saturday on
Sunday off
Monday on
and so on. I did my code well, but when I manage select input
option values to on and off it return back to its default when I close
the app or go to another page. So the question is how can keep with
select options values for first time as user selected? Also, if I want
to play sound in specific time as:
Saturday on
5.30am how can I do it?
<play sound method>
public class WebAppInterface {
Context mContext;
public MediaPlayer mp = null;
public static boolean checked = false;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
mp = MediaPlayer.create(mContext,R.raw.sound);
}
#JavascriptInterface
public void playsound(String value ) {
if (value.equals("on")){
checked = true;
mp.setLooping(true);
mp.start();
}
else
{
checked = false;
mp.stop();
}
}
}
HTML code:
<html>
<form >
<select name="flip-1" id="flip-1" data-role="slider" onchange="getAzan(this)" >
<option value="off" >play</option>
<option value="on">off</option>
</select>
</form>
<script type="text/javascript">
function getAzan(sel) {
var value = sel.options[sel.selectedIndex].value;
Android.playsound(value);
}
</script>
Note: I did play sound when user select on value at the code up
I'd say it would be better to save those things into SharedPrefences instead of storing it on a file.
To use SharedPreferences it's pretty simple. When you get the value (i.e.: on or off), just open the SharedPreferences, and put those values in it.
private void editPlayMonday(boolean shouldIPlay) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putBoolean("PlayMonday", shouldIPlay).commit();
}
Once your values are in place, if you want to know if you have to play a song, just check the SharedPreferences, and look what's in it that way:
private void playSong() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean shouldIPlay = prefs.getBoolean("PlayMonday", false);//false being the default value
if(shouldIPlay) {
//play song or whatever
}
}
Now, you can have a boolean in your preferences for each days, and just check if these values or on or off for today's date.
I hope it helps!
EDIT:
So, up there I gave you the keys to manage your player, and when the sound needs to be played. The editPlayMonday function let you register on your application when you need to play your sound, and playSong lets you check the preferences to know if you have to play your song.
Now, in your application, you need to use those functions and link them to the javascript. I'll let you do it, I'm pretty sure there is a lot of tutorials and help about that (i.e.: http://developer.android.com/guide/webapps/webview.html)
The part that I didn't give the details //play song or whatever, in the playSong functions would be a bit more trickier and you should detail a bit more what you want to do with it. What I would advise you to do is to check out the AlarmManager class. It lets you schedule events from your app easily. See the doc for more information or this tutorial on how to implement it.
So to summarize, what you need to do with your application:
Link your HTML switch to the Android editPlay... function so that you can register when you need to play a song.
When you open your webview, check if the SharedPreference corresponding to each days is true or false. This way you can modify the different HTML switch to be on "on" or "off".
In the editPlay... function, and using the AlarmManager, you should schedule an alarm for the next day scheduled, which will link to your song. Remember to check in the SharedPreference if the boolean for the given day is still true. You don't want to play a song the wrong day...
Why don't you keep these values in a database? Or if it's only a few settings you want to remember then just save a file locally and read from it upon starting the application every time.
With regards to your timing question, I think this post should help you Binding MediaPlayer to be played at a specific time .
EDIT
PrintWriter writer = new PrintWriter("nameTheFile.txt", "UTF-8");
writer.println(name);
writer.println(value);
writer.close();
Should write in the file.
Read using:
String name;
Boolean value;
BufferedReader reader = new BufferedReader(new FileReader("/path/to/file.txt"));
String line = null;
while ((line = reader.readLine()) != null) {
name=line;
value=Boolean.Parse(line);
}
As described by #MagicMicky you can use SharedPreferences to store the values in onPause() method
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putBoolean("Monday", true).commit();
and then retrieve the values in onResume().
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean check_monday=prefs.getBoolean("Monday",false); //false being default value
Now your data will be saved even if a user exits the app or move to new activity. As far as Alarm is concerned use AlarmManager different example here to schedule an alarm by checking SharedPreferences for any need for alarm i.e schedule alarm if check_monday==true.
Related
I am a web developer and am trying to develop an application that basically is a Webview that can receive instructions through push requests to redirect the user to specific pages. It is already functional, I just need to correct an issue:
I have tried to make a function in the class that receives and processes the push information that updates the contents of the Webview. But there is some conflict and it is impossible to do so, because one class is static and the other not due to their inheritance.
The way I found around this was creating an string variable inside my "watch messages class" started with "EMPTY" value that receives the value sent in a specific field within the push request 'date' when the notification is clicked. There's my public class FireBaseWatchMessages that extends FirebaseMessagingService:
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d("LOG_ONRECEIVE_1", "From: " + remoteMessage.getFrom());
if (remoteMessage.getData().size() > 0) {
Log.d("LOG_VALID_DATA", "Message data payload: " + remoteMessage.getData());
}
if (remoteMessage.getNotification() != null) {
Log.d("LOG_NULL_NOTIFICATION", "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
Map<String, String> data = remoteMessage.getData();
sendNotification(remoteMessage);
if (data.containsKey("appReportedAction")) {
Log.d("SET_ACTION", "/appReportedAction/" + data.get("appReportedAction"));
NEW_URL_FROM_ACTION = MainActivity.SSLPROTOCOL + "://" + MainActivity.MAIN_URL +"/appReportedAction/" + data.get("appReportedAction");
}
}
In my MainActivity there's a function to change webview content. It works like this:
public void changeViewContent(String actionView){
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.activity_main_webview);
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
if(FireBaseWatchMessages.NEW_URL_FROM_ACTION != "EMPTY"){
mWebView.loadUrl(FireBaseWatchMessages.NEW_URL_FROM_ACTION);
} else {
mWebView.loadUrl( SSLPROTOCOL + "://" + MAIN_URL + actionView);
}
mWebView.setWebViewClient(new HelloWebViewClient());
}
So when the application opens it checks if this variable has a value other than "EMPTY", if so Webview opens the modified URL according to its value, not the default URL.
It happens that when the application is closed when clicking on the message sent by the push the URL doesn't open with the appropriate modifications, as if the variable was not really receiving the value sent by the push.
Using the app debugger I noticed that its log commands do not appear on the console when it is not open, which makes me believe that the function does not really run when the application is closed.
Any idea how I can correct this behavior? How can I make the action of clicking the notification send the parameter to the webview?
I want to first say that your approach is uncommon and I do not recommend storing url in such a manner, since services can be killed/stopped (by user or device) and so you lose your data or the device was turned off so you lose your data. So instead of using variables I have made two methods using Shared Preferences its easy and the storage is permanent in the device even when your app is not in use!
HERE HOW:
The first method is:
public boolean addNewUrl(Context context, String url) {
SharedPreferences sharedPref = context.getSharedPreferences("SHARED URL", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("url", url);
return editor.commit();
}
Define the first method in the FireBaseWatchMessages and it stores the URL and returns true if successfully stored.
And the second is:
public String getUrlAndSetEmpty(Context context) {
SharedPreferences sharedPref = context.getSharedPreferences("SHARED URL", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
String current_url = sharedPref.getString("url", "EMPTY");
editor.putString("url", "EMPTY");
editor.apply();
return current_url;
}
Define this in the MainActivity to get Url returned and also sets the url to "EMPTY" after its takes it!
The first method will be called from the Service FireBaseWatchMessages. This will accept context which for our case it is this or FireBaseWatchMessages.this and it will also accept a URL in form of a string so change your URL into a String. It will then store it in your app internal storage as url!
So just call:
addNewUrl(this,your_url_string);
The second method will be called in the MainActivity or any activity that you want it to work. So define it in the MainActivity. What it does it check if there is a url stored in the storage if it doesn't find any it returns String "EMPTY" and if it finds it it returns it as a current url and also change the value of the stored String to empty because it has already got one. So just call:
String url= getUrlAndSetEmpty(this);
And cheers the url returned can be a really URL STRING OR just a String "EMPTY". Handle the Logic.
This is the best APPROACH for your case! It works any time! It does not depend if the app is visible on foreground or not!
Check your code if you handled the intent correctly on Activity creation!
But also in java when we compare Objects( String included) we use the (Object1.equals(Object2)) instead of (=) sign. So change the line where you called:
if(FireBaseWatchMessages.NEW_URL_FROM_ACTION != "EMPTY")
Change to:
if(!((FireBaseWatchMessages.NEW_URL_FROM_ACTION).equals("EMPTY")))
Do not forget the ! sign there in the condition!
If that doesn't work check the Intent you used to start the Activity.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 2 years ago.
Improve this question
I am planning on implementing a reward system in my android application where users of the application can gain 100 points each day for opening the app. Users can only get 100 points at one given day no matter how many times more then once they open the app. I am not sure how I can go about doing this, for example, a application called WhatsChat, give users credits for opening the app each day:
I am trying to implement a similar system but instead only give users 100 points for opening the app each day. I understand I will need to keep track of the day and maybe store this in local storage using SharedPreferences and keep record of the dates of each day and then increments the variable that records points by 100.
In pseudo code it would look something like this:
Set CreditsGained to 0
IF app launched for the first time on Current date THEN
CreditsGained = CreditsGained + 100
Else
Do nothing
How can I implement a such system in my application?
You do it on the server. The first time they make a network request every day, add 100 points to their total. There's no way to do this securely client side.
I recommend you not use Shared Preferences to save data like you want. Cos they can modify it.
Only 1 way you can secure it, you have to have your own server to keep it. Local storage is not safe too.
But if you want to know how to check that, for studying, you can use Shared Preferences as well.
Step1: get your current time in string:
SimpleDateFormat sdf = new SimpleDateFormat("d-m-Y");
Calendar cal = Calendar.getInstance();
String dateInStr = sdf.format(cal.getTime());
Step2: Check at startup activity.
After onCreate()
SharedPreferences pre=getSharedPreferences("my_sp", MODE_PRIVATE);
SharedPreferences.Editor edit=pre.edit();
if (pre.getBoolean(dateInStr, false)){
//they checked today
}else{
//not today
// use check function here
edit.putBoolean(dateInStr, true);
edit.commit();
}
Okay, put step 1 code above step 2 code, i only separate it for easier understanding.
Step3: After you can check if they have check point more than 1 time or not. Let's add them 100points if that is the first time of the day they check out.
Put this inside else statement, above edit.putBoolean(dateInStr, true);
//get prev_score from SP
long previous_score = pre.getLong("score", 0);
//add 100
previous_score = previous_score + 100;
//save back to SP
edit.putLong("score", previous_score);
I may be late answering to your question..but for others seeking for the reward system and do not want the servers to handle this stuff -->
You can
check whether the Automatic Date and time option is enabled or not in
the user's device
**. Then according to the response, you can give reward to the user.
eg.
calendar= Calendar.getInstance();
year=calendar.get(Calendar.YEAR);
month=calendar.get(Calendar.MONTH);
day=calendar.get(Calendar.DAY_OF_MONTH);
todaystring= year+ "" + month + "" + day + "";
timepref=context.getSharedPreferences("REWARD",0);
currentday=timepref.getBoolean(todaystring,false);
//Daily reward
if (!currentday && isZoneAutomatic(context) && isTimeAutomatic(context)) { //currentday =false
btnrwrd.setEnabled(true);
btnrwrd.setText("Collect your daily reward!");
btnrwrd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "Daily reward granted!", Toast.LENGTH_SHORT).show();
// Do your stuff here
// saving the date
SharedPreferences sharedPreferences = context.getSharedPreferences("SAVING", Context.MODE_PRIVATE);
SharedPreferences.Editor edt = sharedPreferences.edit();
edt.putInt("mypoints", Integer.valueOf(points.getText().toString()));
edt.apply();
Toast.makeText(context, String.valueOf(daily), Toast.LENGTH_SHORT).show();
SharedPreferences.Editor timedaily = timepref.edit();
timedaily.putBoolean(todaystring, true);
timedaily.apply();
btnrwrd.setText("Wait for 24 hrs");
btnrwrd.setEnabled(false);
}
});
}
else {
Toast.makeText(context, "Your daily reward is over!", Toast.LENGTH_SHORT).show();
}
public static boolean isTimeAutomatic(Context c) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.Global.getInt(c.getContentResolver(), Settings.Global.AUTO_TIME, 0) == 1;
} else {
return android.provider.Settings.System.getInt(c.getContentResolver(), android.provider.Settings.System.AUTO_TIME, 0) == 1;
}
}
public static boolean isZoneAutomatic(Context c) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
return Settings.Global.getInt(c.getContentResolver(), Settings.Global.AUTO_TIME_ZONE, 0) == 1;
} else {
return android.provider.Settings.System.getInt(c.getContentResolver(), android.provider.Settings.System.AUTO_TIME, 0) == 1;
}
}
I hope it helps you! Upvote the answer and Good luck :)
Whenever the user opens the app, check if any last credit date is available in the local storage and if it does, verify the current date is one more than the stored date, then you credit the user for next day.
If the date is not available in storage, then you can assume it's the first day. And yes you can do it in MainActivity for this use case because you are not making any time consuming api calls.
I just shared the idea, figure out the code. It's easy.
i have created android app that require users to enter their phone numbers when they first use the app, now i am storing that info using SQL lite.the problem is every time they open the app it requires their phone number, and I want the app to just automatically login without asking for the phone number again, kind of like whats app.
Its not about landing page change. The activity which has a category "LAUNCHER" in manifest file always opens first. In that Activity .java file , You can make a check , whether the value for user is available in sqlite or not. if available perform intent to next page .. Check this link too ......Android check user logged in before, else start login activity
Either set a splash activity or another blank activity as your initial activity.
Then store a boolean in your app's shared preference to identify whether the application
is loading first time or not. Based on that boolean value, move to phone number entry screen or
your desired screen.
In your "login" activity you should look for the number in the db, if it is there, you open a new activity, if not, you ask the user. You can use setVisibility(int) in your "ask" views to not show them while looking in the db, and then, if you don't find the number, you show them.
You have to use sharedPrefrences where you can store whether user has stored his number.
When user open the app for the first time and enter his number, then store value in sharedprefrences.
SharedPreferences sharedpreferences;
sharedpreferences = getSharedPreferences("prefrence", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString("value", "selected"); editor.commit();
When user open the app, Splash screen will check the value in sharedprefrences. If user already had put his number then he will be re-directed to home screen rather than phone number screen.
Splash Screen:
Context mContext;
// Splash screen timer
private static int SPLASH_TIME_OUT = 3000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
mContext = SplashScreen.this;
new Handler().postDelayed(new Runnable() {
/*Showing splash screen with a timer. This will be useful when you
want to show case your app logo / company*/
#Override
public void run() {
// This method will be executed once the timer is over
// Start your app main activity
SharedPreferences shared = getSharedPreferences(PREF_NAME, MODE_PRIVATE);
String value = (shared.getString("value", ""));
if(value!=null && !value.equals("")){
/*Re-Direct to Home Screen after Login*/
Intent intent = new Intent(mContext,MainActivity.class);
startActivity(intent);
}
else{
Intent intent = new Intent(mContext, LoginActivity.class);
startActivity(intent);
}
// close this activity
finish();
}
}, SPLASH_TIME_OUT);
}
Hi I want that the application that I have developed to stop working after like 5 days. In short I want to time bomb my android app Can someone tell me how to do this programmatically in android studio? Any possible codes to suit this?
Thanks..
Use the following method to get the timestamp of the moment, when the app was installed for the first time:
private static long getFirstInstallTime(Context context) throws
PackageManager.NameNotFoundException {
PackageManager pm = context.getPackageManager();
PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
return info.firstInstallTime;
}
Now you can calculate the elapsed time and compare it with your desired app lifetime:
long now = System.currentTimeMillis();
if (now - getFirstInstallTime(getApplicationContext()) >
TimeUnit.DAYS.toMillis(5)) {
sendPoisonPill();
}
Note: sendPoisonPill method is your implementation of 'time bomb'
Well,
if you know the time of publications then you can do something (silly) as
class MainActivity extends Activity {
public static final long DESTROY_APP_TH = 432000000;
#Override
protected void onCreate(Bundle savedInstanceState){
PackageManager pm = context.getPackageManager();
PackageInfo pi= pm.getPackageInfo(context.getPackageName(), 0);
long publishTimeInMilli = pi.firstInstallTime;
long now = System.currentTimeMillis();
if(now - publishTimeInMilli) > DESTROY_APP_TH) {
//just finish the the activity (and thus the app) or do something else
finish();
}
}
I am using this code to expire trial version after 26th March.
String currentTime = new SimpleDateFormat("yyyyMMdd").format(Calendar.getInstance().getTime());
Log.d("timeStamp", currentTime);
Calendar date = new GregorianCalendar(2016, Calendar.MARCH, 26);
date.add(Calendar.DAY_OF_WEEK, 0);
String expireTime = new SimpleDateFormat("yyyyMMdd").format(date.getTime());
int intcurrentTime = Integer.parseInt(currentTime);
int intexpireTime = Integer.parseInt(expireTime);
if(intcurrentTime == intexpireTime || intcurrentTime > intcurrentTime ) {
//logic to set off the features of app
tvJ2.setText("Trial period expired!!");
}
You can use AlarmManager to send an intent to your app at the specified time. Have that intent handler close your app.
Please bear in mind, however, that depending on what exactly you want to do, this is, likely, not a good thing. An Android app running (i.e. - has a process that gets scheduled by the kernel), open (i.e. - has a view that the user can change to) or active (i.e. - it is the foreground view) are almost independent states. You need to specify which is what you want to expire.
You could create app with subscription, such that after 5 days subscription expires and app becomes useless (can't be started)
In my implementation, I will add 1 variable to SharedPreference.
for example firstRun timestamp. Each time the app launch, I will get that variable and check it with the current time of the app. It is longer than 5 days (your setting), so terminate the app. But this way can't help if users change system time in their device.
The safer way is you should send this variable firstRun to your server. And each launching time, the app will request server and check condition inside your server.
Hope it helps!
I don't understand why do you want to do that, but anyway, you could create a String with a date and save it to SharedPreferences. In your main activity, before doing anything you compare the actual date with the date that you have saved in SharedPreferences (the saved date could be the first time that the application was opened or a prefixed date) and if the actual date is 5 days or more after your saved date, you can display a blank activity or whatever you want.
I have erite for you a code, where the first time you open the app the system saves the date and adds 5 days more. Then every time you open again the app you compare the saved date with the actual date, and if the actual date is after your saved date (it means that it has passed 5 days) you do whatever you want
class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState){
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
if (!prefs.getBoolean("firstRun", true) {
SharedPreferences.Editor editor = prefs.edit();
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.DATE, 5); // number of days to add
String date = sdf.format(c.getTime()); // dt is now the new date
editor.putBoolean("firstRun", true);
editor.putString("valid_until", date).apply();
}
else if(new Date().after(sdf.parse(prefs.getString("valid_until","")))) {
//Show whatever you want. Or finish the activity calling to finish();
}
}
I haven't tested this on any other devices but on a 2.1 device, in a WebView with the zoom controls turned on, a toast message sometimes comes up that says something like "Tip: double tap to zoom in and out". I don't know where it is coming from as nothing in my code asked for it to appear. Is there any way to disable this?
I don't know how to reproduce it but it seems to happen more often when the app is freshly installed.
As indicated in wajiw's answer, the toast is based on the double tap toast count in WebSettings. There is a workaround based on preempting that value. WebSettings gets its value for double tap toast count from SharedPreferences. Overriding the preferences value will disable the toast.
The preferences are based on private values in WebSettings so it's not ideal. If the implementation changes, this could very well stop working. So, use at your own risk.
Here are the values WebSettings uses for the SharedPreferences. You'll need to duplicate them in your class.
private static final String PREF_FILE = "WebViewSettings";
private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count";
Then, you'll need to change the values before you use the WebView
SharedPreferences prefs = context.getSharedPreferences(PREF_FILE, Context.MODE_PRIVATE);
if (prefs.getInt(DOUBLE_TAP_TOAST_COUNT, 1) > 0) {
prefs.edit().putInt(DOUBLE_TAP_TOAST_COUNT, 0).commit();
}
Check out WebSettings source code for more info.
From looking at the WebView.java source it's coming from the startDrag function:
private void startDrag() {
WebViewCore.reducePriority();
// to get better performance, pause updating the picture
WebViewCore.pauseUpdatePicture(mWebViewCore);
if (!mDragFromTextInput) {
nativeHideCursor();
}
WebSettings settings = getSettings();
if (settings.supportZoom()
&& settings.getBuiltInZoomControls()
&& !getZoomButtonsController().isVisible()
&& mMinZoomScale < mMaxZoomScale
&& (mHorizontalScrollBarMode != SCROLLBAR_ALWAYSOFF
|| mVerticalScrollBarMode != SCROLLBAR_ALWAYSOFF)) {
mZoomButtonsController.setVisible(true);
int count = settings.getDoubleTapToastCount();
if (mInZoomOverview && count > 0) {
settings.setDoubleTapToastCount(--count);
Toast.makeText(mContext,
com.android.internal.R.string.double_tap_toast,
Toast.LENGTH_LONG).show();
}
}
}
the settings are accessible through getSettings(). From there I would try to call setDoubleTapToastCount and use something like 0 or -1 for the value. If that doesn't work you may be out of luck.
See full source of WebView.java here