Flutter Create Spawns app That Contains Unexpected Folders and Files - flutter

The bounty expires in 7 days. Answers to this question are eligible for a +50 reputation bounty.
Nerdy Bunz is looking for a canonical answer.
About a week ago, I created a new flutter project using:
flutter create -t app my_app
But when I opened the resulting project in the IDE, I was surprised to find the project has some key differences compared to what I'm used to:
there is a folder inside the lib folder, "src"
the main.dart does not contain the usual "counter app" and looks like this:
import 'package:flutter/material.dart';
import 'src/app.dart';
import 'src/settings/settings_controller.dart';
import 'src/settings/settings_service.dart';
void main() async {
// Set up the SettingsController, which will glue user settings to multiple
// Flutter Widgets.
final settingsController = SettingsController(SettingsService());
// Load the user's preferred theme while the splash screen is displayed.
// This prevents a sudden theme change when the app is first displayed.
await settingsController.loadSettings();
// Run the app and pass in the SettingsController. The app listens to the
// SettingsController for changes, then passes it further down to the
// SettingsView.
runApp(MyApp(settingsController: settingsController));
}
I tried creating other new projects and I verified it also happened when using "flutter create -t skeleton."
Now, after a week, it seems to have gone back to the old behavior.
Does anyone know the explanation for this?

Related

Flutter widget preview

Let's suppose i am debugging an already built app and i needed to see the widget/screen and how it looks(without running the application and going through all the different screens to reach the desired one) ,
i know there is an annotation (#preview) in jetpack compose for native android to preview the widget in question isolated from the whole app ,
in the meantime to preview a certain widget i put it in
void main() => runApp(ParticularScreen());
is there any other option ?
ps : i think there is a plugin for vs code called preview
https://marketplace.visualstudio.com/items?itemName=jamesblasco.flutter-preview
i am looking for exactly the same but with android studio

Flutter not loading HomePage during first run, but loads properly with Hot Reload

I created a navigation menu with the home page as the starting item, but after editing my HomePage and running the app it only shows text with "Home Page" in the center. When I do Hot Reload, it works properly, but not on the first run (Also to note, this occurs only for iOS run, it works properly for Android)
UPDATE: I changed the name of the application via Xcode. So, then in ios/Runner.xcodeproj/project.pbxproj find /* Debug */ = { section, and there change value of PRODUCT_NAME to Runner. After that use flutter clean && flutter run to run the app. It should fix the issue.

Error: Entrypoint doesn't contain a main function Flutter

I got an error Error: Entrypoint doesn't contain a main function Flutter, I tried to restart android studio but it did not work
Depends on what the program is support to do. There should be a main class that is initiated. As an example:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(MyApp()); // initiate MyApp as StatelessWidget
// Main class
class MyApp extends StatelessWidget {
// creating main screen and building list of wordpairs
#override
This worked for me:
When new project is created then got the error "Entrypoint doesn't contain a main function Flutter".
To resolve this I followed below step
First make sure your flutter and dart sdk paths are properly configured.
You can re-include the files/project root folder.
Goto File -> Project Structure -> Module
And then add the root folder of the project by clicking + icon, then it will detect a flutter app again.
Build the project and check for the error.
add main function to your project. you might miss that
void main() => runApp(MyApp());
There's another case where this is possible, because of dart package file
delete all that .packages files, should get resolved.
Just do this
File -> Project structure -> Modules
From right select
Sources
form [Source, Paths, Dependencies] Tabs
Select Plus Icon -> Apply -> ok button
Make sure you use same name of project and pubspec.yaml file name Sometime it happens when we copy one pubspec file for another project.
in my case the launching function was named something else, renamed it to main, then it worked.
Add this if its missing in your main.dart file
void main() => runApp(MyApp());
This function tells Dart where the program starts, and it must be in the file that is considered the "entry point" for you program.
I cut some text above the main function and that included a closing } which made the main inside some class above it. That caused the above error. I put back the } above main and everything became ok.

Using uni_links when the app is in the background

My application has the following structure:
- InheritedWidget for dependencies
--> Splash Screen Page
--> Login Pages
--> Main Pages
When the app runs for the first time, I can use var link = await getInitialLink(); to get the value for the link that opened the app.
However, I cannot get the same result if I open the app on the background.
I tried to use
getLinksStream().listen((link) => (link) {
try {
var _latestUri;
if (link != null) _latestUri = Uri.parse(link);
print("=== Formated successfully a link!");
} on FormatException {
print("--- A link got here but was invalid");
}
});
For getting the link in the Splash Screen, but if the app is already open in the Login or Main pages, it won't go through the Splash Screen again.
Then, I tried to put it in the InheritedWidget, but alas, didn't get any result whatsoever.
So my question is: Where and how should I set up uni_links so that I can catch all incoming links even if the app is open?
Or better, is there an alternative for App Links/Universal Links that I can use?
Though it's not the best and most elegant way, I got around this.
First, I was not using getLinksStream correctly
Instead of
(link) => (link) {...}
It's
(link) {...}
Then, I need to put this subscription in my Splash Screen and do not dispose of it, so that it can listen to new events.
If anybody has a better solution, please free to add it
For this situation, you need to use both of getInitialUri() and getUriLinksStream(),
If app launchs directly u will get uri from getInitialUri, if app already running on background u will get uri from getUriLinksStream.

Accessibility Permissions for Development in macOS and XCode

Is there a way to give an app I am developing in XCode accessibility permissions by default during development. The idea is that I could hit the run key and test the new code without having to jump through the hoops in the settings. For deployment obviously it wouldn't work, but for development is there a way to basically whitelist the app?
EDIT: This is a new method I've found/created that is working and has the added benefit of prompting the user first too, improving the onboarding experience of your app. The original method (which I've left at the bottom of this post) still prompted for accessibility on each new build of the app unfortunately.
I had to get this working in my macOS app and had another idea and way to approach it, given the user needs to action it anyway, I just have the app present the required dialogue on each run and during the app build, I run a script to clear the existing permissions.
For reference, see v1.3.0 of my Auto Clicker macOS app, specifically:
Services/PermissionsService.swift (whole class)
Init/AppDelegate.swift (line 21)
Init/AutoClickerApp.swift (line 32 & 40)
auto-clicker.xcodeproj/project.pbxproj (line 435)
The links are links to the tagged version, so should never change or break. There is quite a bit of code, I'll try to summarise here.
Firstly, I created a new class to manage permissions related functionality to keep things contextual:
//
// PermissionsService.swift
// auto-clicker
//
// Created by Ben on 10/04/2022.
//
import Cocoa
final class PermissionsService: ObservableObject {
// Store the active trust state of the app.
#Published var isTrusted: Bool = AXIsProcessTrusted()
// Poll the accessibility state every 1 second to check
// and update the trust status.
func pollAccessibilityPrivileges() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.isTrusted = AXIsProcessTrusted()
if !self.isTrusted {
self.pollAccessibilityPrivileges()
}
}
}
// Request accessibility permissions, this should prompt
// macOS to open and present the required dialogue open
// to the correct page for the user to just hit the add
// button.
static func acquireAccessibilityPrivileges() {
let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true]
let enabled = AXIsProcessTrustedWithOptions(options)
}
}
Then, I added the following to my AppDelegate (baring in mind this was in Swift UI):
//
// AppDelegate.swift
// auto-clicker
//
// Created by Ben on 30/03/2022.
//
import Foundation
import Cocoa
final class AppDelegate: NSObject, NSApplicationDelegate {
// When the application finishes launching, request the
// accessibility permissions from the service class we
// made earlier.
func applicationDidFinishLaunching(_ notification: Notification) {
PermissionsService.acquireAccessibilityPrivileges()
}
}
Then finally, in our Swift UI app init, lets add some UI feedback to the user that we are waiting for permissions and listen to that isTrusted published property we setup earlier in the permissions service class that gets polled every second to unlock the UI when the user has granted the required permissions:
//
// AutoClickerApp.swift
// auto-clicker
//
// Created by Ben on 12/05/2021.
//
import Foundation
import SwiftUI
import Defaults
#main
struct AutoClickerApp: App {
// Create an instance of the permissions service class that we
// can observe for the trusted state change.
#StateObject private var permissionsService = PermissionsService()
var body: some Scene {
// Wait for trust permissions being granted from the user,
// displaying a blocking permissions view telling the user
// what to do and then presenting the main application view
// automatically when the required trust permissions are granted.
WindowGroup {
if self.permissionsService.isTrusted {
MainView()
} else {
PermissionsView()
}
.onAppear(perform: self.permissionsService.pollAccessibilityPrivileges)
}
}
}
You can see the blocking view I made in the app above, Views/Main/PermissionsView.swift.
Then in order to automatically clear the permissions during the app build, I added a new build script to the project that runs the following against /bin/sh:
tccutil reset Accessibility $PRODUCT_BUNDLE_IDENTIFIER
As seen in auto-clicker.xcodeproj/project.pbxproj (line 435).
This means I'll be prompted with the system dialogue on each app build to just press the + button and add the app.
Unfortunately this is the most frictionless way I've found to develop the app with these permissions being required.
Outdated answer:
Found a way to do this after some trial and error, navigating through Xcode's (>11, currently 13) new build system.
With Xcode open and having it as the foreground app (so it takes over the menu bar with its menu items), do the following:
From the menu bar, select 'Xcode'
If your project doesn't yet have a workspace, click 'Save as Workspace...' near the bottom of the list and save the Workspace alongside your *.xcodeproj so they should be in the same directory. From now on you'll open your project via the new *.xcworkspace Workspace instead of your *.xcodeproj Project.
From the menu bar, select 'Xcode' again
Click 'Workspace Settings...' near the bottom of the list
Under 'Derived Data' select 'Workspace-relative Location', if you want to customise the path do so now
Click 'Done' in the bottom right
This puts the build location of our *.app binary within the project so its easy to find, along with also allowing us to check the change into source control as we now have the Workspace settings stored in the *.xcworkspace file.
Next we need to now point the permissions at the above build binaries location, so:
Open System Preferences
Click 'Security & Privacy'
Click the padlock in the bottom right to make changes
Select 'Accessibility' from the left side list
Click the plus button at the bottom left of the list and find the *.app file to add it to the list that we put within the project directory, this should be something like $PROJECT_DIR/DerivedData/$PROJECT/Build/Products/Debug/*.app
Click the checkbox to the left of the app to check it if its not already checked
Restart the app
Any builds should now have the relevant permissions.
Just to note though, this will overwrite the permissions of any archived/prod builds as the app names and binaries are the same. They are easily added back though, just delete the permission for the build app and instead point it back at your prod app, usually in /Applications.