Is it possible to ensure that after a fresh install of my code-pushified react-native app the user gets the latest deployed bundle from code-push?
My intention is to ensure that the user will always get the latest version of my app even after opening it for the first time.
EDIT 1
I am already aware of code-push configurations such as InstallMode and checkFrequency. I am currently using the less intrusive installMode = ON_NEXT_RESTART.
The scenario I want to avoid is the following: I first publish my app on the Play Store (let's do an Android example) with version 1.0.0. After, let's say, 6 months and a lot of new features and bug fixes my app is on version 1.0.27. If I only published the updates (the new versions) on code-push then the original apk available in Play Store still contains the bundle version 1.0.0. This means that any new user opening the app for the first time, right after installation, will get the 6-months-old 1.0.0 version without any of new the features and fixes that the latest version includes. Only after restarting the app (let's say it happens on the next day) the user will get the 1.0.27 version from code-push (remember that I am using installMode = ON_NEXT_RESTART).
The obvious solutions for this are:
Publish a new apk on the Play Store for every new version of my app (besides, of course, publishing it on code-push).
Use a more intrusive installMode.
Mark every single code-push release as a mandatory install.
I am ok with the 1st option (and the 1st option only). I wanted to check if there is another option I am not aware of. To be honest I don't know if what I want is actually possible to do with code-push.
As per discussion in comments, what you wish to achieve can be achieved using manual updates of code push. To do so, you can set a variable in AsyncStorage to denote that you have opened app at least once, and if that doesn't exist control & immediately update the app. An example can be seen below;
class MyApp extends Component {
componentDidMount() {
AsyncStorage.getItem('#AppHasOpened').then((appHasOpened) => {
if (!(appHasOpened && appHasOpened === 'yes')) {
AsyncStorage.setItem('#AppHasOpened', 'yes').then(() => {
codePush.sync({
installMode: codePush.InstallMode.IMMEDIATE,
});
});
}
});
}
}
Related
I have a live app which is used by other clients. after i made changes on dev environment i'm deploying the app. Naturally the cliend doesn't do hard refresh but the client needs to do hard refresh in order to see the changes i've made.
What can i do ?
When your app is deployed, it is actually built with some new assets and the code doesn't need any update because the cache is invalidated (if the deployment is done well).
Service workers may persist but this is a different thing.
This was and still is a duplicate, see here.
Well First Answer worked for me, Which is updating the app version in the package.json
For example by default the version number is set to "0.1.0"
package.json file:
{
"name": "project-name",
"version": "0.1.1",
"private": true,
...
}
I've got a node API that uses firebase-admin to handle firestore data. This wasn't a problem till a few days ago and now it started happening.
The weird thing is, I only seem to get this on my production server and not on local development environment(even using the same database).
I've tried redeploying, restarting the server, checked database configuration and everything and nothing really worked.
This is one of the more detailed errors:
Error: 14 UNAVAILABLE: Getting metadata from plugin failed with error: URL is not a constructor
at Object.exports.createStatusError (/root/apps/api/src/node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (/root/apps/api/src/node_modules/grpc/src/client_interceptors.js:1204:28)
at InterceptingListener._callNext (/root/apps/api/src/node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (/root/apps/api/src/node_modules/grpc/src/client_interceptors.js:618:8)
at callback (/root/apps/api/src/node_modules/grpc/src/client_interceptors.js:845:24)
And this is my connection file:
import * as admin from 'firebase-admin'
import serviceAccount from './fbAdminKey'
admin.initializeApp({
projectId: '<myProjectId>',
credential: admin.credential.cert(serviceAccount),
databaseURL: '<myDbURL>'
})
const db = admin.firestore()
const messaging = admin.messaging()
const auth = admin.auth()
export default { db, messaging, auth }
It should be able to just connect to the database and do the operations, I have an app, a web application and they all work normally, just the node API seems to be acting weirdly.
So, after banging my head around for nearly a week, having other problems and stuff, I could figure it out with the help of everybody here.
The problem was the node.js version
I was running node 8.4.0 locally and node 6.x.x on production. (firebase-admin 7.0.0)
So I updated it on production using nvm and than got another problem, related to the grpc version. I had a newer version installed and it was requiring an older one.
Note
If you are using PM2, make sure to update it as well:
http://pm2.keymetrics.io/docs/usage/update-pm2/
After that it started working again and it stuff is back on track.
Not the exact solution because it doesn't solve the problem with Node 6.11.5.
The production server runs by default on Node 6.11.5 and if you wanted to change the runtime version to 8, then refer to this article.
https://firebase.google.com/docs/functions/manage-functions#set_runtime_options
However, keep in mind that this runtime version is currently in beta, so it might break.
I also noticed, that I was able to get rid of this error that you were facing by installing previous version of firebase-admin (6.2.0 to be specific, as for now - the version 7.x.x is the latest one).
I'm afraid that one of the newer firebase-admin versions broke this feature in some environments and that's why this issue is not that common.
I built an Electron app and I am now looking at how to distribute it.
I went with electron-builder to handle packaging etc.
For a bit of context, as a web developer, I am used to continuously deploy web apps on a web server but I have a hard time figuring out how to distribute a packaged one in Electron.
In electron-builder docs there is a brief mention about testing auto-update:
"Note that in order to develop/test UI/UX of updating without packaging the application you need to have a file named dev-app-update.yml in the root of your project, which matches your publish setting from electron-builder config (but in YAML format)"
But, it's rather vague...
So I actually have two questions:
1. How do I actually test the auto-update flow?
Do I need to actually publish a new version to trigger an update locally? Seems pretty unclear, it would be like developing against the production server.
2. Is it possible to have a fallback for unsigned code?
I don't have yet any certificate for code signing. So the OS/app will block the auto-update. But, I'd still want to tell the user that an update is available so they can go and download the app manually. Can I do that? (going back to point 1, I'd like to be able to test this flow)
I've just finished dealing with this. I also wanted to test against a non-production server and avoid having to package my app each time I iterated. To test downloads I had to sign my app, which slowed things down. But it sounds like you just need to check for updates. Which I think you can do as follows...
I created a dummy github repo, then created a a file dev-app-update.yml containing:
owner: <user or organization name>
repo: dev-auto-update-testing
provider: github
The path where this file is expected to be defaults to a place you can't access. Thankfully, you can override it like so:
if (isDev) {
// Useful for some dev/debugging tasks, but download can
// not be validated becuase dev app is not signed
autoUpdater.updateConfigPath = path.join(__dirname, 'dev-app-update.yml');
}
...that should be enough for your case -- since you don't need downloads.
If not, here are some other tips:
you can change the repo setting in your electron-builder config to point at your dummy repo then package your app. This will give you a packed, production build that points at your dummy repo -- this is how I did my download testing (though I have a cert, and signed my app)
you should be calling autoUpdate's checkForUpdates(), but if checkForUpdatesAndNotify() gives you a useful OS Notification then you should be able to set autoUpdater.autoDownload to false and end up with what you need.
Lastly, it sounds you could skip autoUpdater, since you won't be using the download feature anyway. Instead you could use github's releases api, assuming you use github to host your release. If not then your host should have something similar. Use that to check for updates then tell the user from within your App (could present them with a clickable URL too). If you want OS Notifications electron has a module for that.
We're using electron-updater with GitHub as a provider for auto-updates. Unfortunately, it breaks a lot and the electron-builder team doesn't support these issues well (1, 2, 3) (from my own experience, but you can find more examples on GitHub).
One way to test updates in dev mode:
Create a build of your app with an arbitrarily high version number
Create a public repo and publish the above build
Create a dev-app-update.yml next to your main entry point and configure it for the repo above (see)
In your main entry point:
import { autoUpdater } from "electron-updater";
...
if (process.env.NODE_ENV === "development") {
// Customize the test by toggling these lines
// autoUpdater.autoDownload = false
// autoUpdater.autoInstallOnAppQuit = false;
autoUpdater.checkForUpdates();
}
Then when running yarn dev you should see something like:
Checking for update
...
Found version 100.0.0 (url: <>.exe)
Downloading update from <>.exe
updaterCacheDirName is not specified in app-update.yml Was app build using at least electron-builder 20.34.0?
updater cache dir: C:\Users\<>\AppData\Local\Electron
New version 100.0.0 has been downloaded to C:\Users\<>\AppData\Local\Electron\pending\<>.exe
And it should install when you close the dev app.
This should give you some certainty but we still ran into issues in production. If you want to be sure, play through the full update flow with a test repo but packaged production apps just as you would do with the live one.
I have version 5.0.1 of my application with two versions released on CodePush.
I do not bump up any Version or Build numbers. So 5.0.1 and Build 1.
The first version v1 gets installed, but after I make a new release (v2), the bundle doesn't get downloaded or installed anymore.
v1:
v2:
I use the following to add CodePush to my app:
const CodePushHomeScreen = codePush(HomeScreen);
Thanks
Default behavior restricts updates to only occur once an app is restarted. I would first confirm that updates aren't being registered after a restart of the app and/or switch things over to update on resume instead using this snippet:
let codePushOptions = { checkFrequency:
codePush.CheckFrequency.ON_APP_RESUME };
class MyApp extends Component {
}
M HomeScreen App = codePush(codePushOptions)(HomeScreen);
If that doesn't work, delete the two updates and release two more using the flag:
--targetBinaryVersion "~5"
I have used Phonegap several times but since the upgrade to Mavericks / Xcode5 everything has changed.
If I try to create a helloworld project, everything looks good: it compiles and launches the simulator or installs the app on my phone. The problem is if I try to add any Phonegap functionality, the it just won't work.
UPDATE: this is how I'm creating the project:
cordova create helloworld
cordova platform add ios
I have tried directly opening helloworld.xcodeproj in Xcode, using the "cordova run ios", "cordova prepare", "cordova build" commands but none of them seems to make any difference (some of these create and copy a lot of files, but there is no difference regarding the access to "device" variable)
The only way of debugging I have managed to use is to show alerts and try/catch blocks like this:
try {
alert(device);
// var text = '';
// var i = 0;
// for (var attribute in window) {
// text = text + '\n' + attribute;
// i++;
// }
// alert("total " + i + " keys: " + text);
} catch (err) {
alert(err);
}
Trying to read from "device" variable results in the following:
The text on this error suggests that one should use the following command
phonegap plugin add thePlugin
That indeed works: it adds the desired feature on the config.xml file, but the problem persits, so it does not look like an issue related to permissions. The same thing occurs when installing and trying to use other plugins, such as accelerometer or notifications.
I really liked Phonegap because it made things easier, but now it seems the opposite. One optoin is to use an older version of Phonegap and/or Xcode, but that's not what I'm looking for.
So, what is my configuration?
Mavericks 10.9.1
Xcode 5.0.2 (5A3005)
Phonegap / cordova 3.3.0
iOS 7.0.4 (iPhone 5) --> or the emulator
Any clues?
Thanks
I finally managed to solve this issue.
The solution is simple, yet it was difficult to detect.
Every time you add a plugin using the following command: cordova plugin add thePlugin you then need to run the cordova prepare command again. This is tricky, because if you take a look at the code after adding the plugin there is some setup/changes made. But these changes aren't enough, so cordova prepare might first seem redundant, but solves the issue.
So:
create the project
add as many plugins as you might use
start developing either:
(a) directly on the generated YOURAPP.xcodeproj file, and NEVER run
the cordova prepare commmand again, otherwise you will delete all your
changes
(b) work on the "general" www folder of your project and then run cordova prepare everytime you need to create a new version. Note:
you'll need to close the xcodeproj file in order to see any changes
I tend to think that alternative "(a)" should be the optimal, just make sure you don't overwrite your files or keep your files properly versioned