I am making an application in Unity3D and I have a problem with the file .obb. After downloading the file .obb from my dropbox try to open the next scene and tells me I can not find it. If I close the application and return open functioning OK. What can be?
using UnityEngine;
using System.Collections;
using System.IO;
using System;
using UnityEngine.UI;
public class DownloadFile : MonoBehaviour {
private string path;
private string url = "";
private float m_CurrentValue = 0;
public GameObject btnStart;
private string nextScene = "Splash";
void log( string t )
{
print("MYLOG " + t);
}
// Use this for initialization
void Start ()
{
CheckObb ();
}
// Update is called once per frame
void Update () {
}
void CheckObb()
{
if (!GooglePlayDownloader.RunningOnAndroid())
{
log ( "Use GooglePlayDownloader only on Android device!");
return;
}
string expPath = GooglePlayDownloader.GetExpansionFilePath();
if (expPath == null)
{
log("External storage is not available!");
}
else
{
string package = GooglePlayDownloader.Package();
int version = GooglePlayDownloader.Version();
path = String.Format("{0}/main.{1}.{2}.obb", expPath, version, package);
url = String.Format("https://www.dropbox.com/s/xxxxxxxxxxxxxx/main.{0}.{1}.obb?dl=1", version, package);
if (File.Exists(path))
{
// After downloading the file if you close the game and you become open, OK ¿?
Application.LoadLevel(nextScene);
}
else
{
//check if directory doesn't exit
if(!Directory.Exists(expPath))
{
//if it doesn't, create it
Directory.CreateDirectory(expPath);
}
btnStart.SetActive(true);
}
}
}
// Click Start button download obb
public void ClickStart()
{
btnStart.SetActive(false);
StartCoroutine(DownloadObb());
}
// Download obb
IEnumerator DownloadObb() {
WWW download = new WWW(url);
while( !download.isDone ) {
m_CurrentValue = download.progress * 100;
yield return null;
}
if (!string.IsNullOrEmpty(download.error)) {
//Error
} else
{
// success!
File.WriteAllBytes (path, download.bytes);
// Here says that there is the scene
Application.LoadLevel(nextScene);
}
}
}
I tried to upload the apk and obb as alpha version in the developer console but when I go to download the .obb tells me this:
"Download failed because the resources could not be found"
Thanks.
I follow this tutorial in order to split my Unity app into *.obb file. It help me a lot.
Now, when I was performing my test in GooglePlay as an Alpha version everything goes OK, the download of the obb file and the process in the app but it doesn`t load my first scene.
It took me a lot to notice that when I put the loader as the scene 0 my index to load the next Scene was wrong. I know it is a poor error but thats the History behind my 10 hours research.
Hope you'll find useful.
Related
I want to download a song from an online server and save it in the device memory. Then recall the saved song from the device memory.
This is done correctly with the following code in Windows, but in the Android platform, only the file is saved correctly, but the file is not called and executed from the device memory and gives an error.
private void Start()
{
Adress = new WWW("**WebAdress**");
}
public void DownloadButton()
{
StartCoroutine(LoadMp3FromWeb());
}
IEnumerator LoadMp3FromWeb()
{
WWW www = Adress;
Adress = www;
yield return www;
System.IO.File.WriteAllBytes((Application.persistentDataPath + ".mp3"), www.bytes);
}
public void LoadButton()
{
StartCoroutine(LoadAudioClip());
}
IEnumerator LoadAudioClip()
{
using (UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip((Application.persistentDataPath + ".mp3"), AudioType.MPEG))
{
yield return uwr.SendWebRequest();
Musics = DownloadHandlerAudioClip.GetContent(uwr);
myClip.clip = Musics;
myClip.Play();
}
}
}
For loading the clip from memory you don't need to send WebRequests to the persistent data path. As that path doesn't exist in the web, it exists on your device only. use System.IO.File.ReadAllBytes instead.
I have a small MAUI app i'm testing with. Im trying to read a file that was part of the deployment. I have the code below, which works great in a Windows deploy of the MAUI app, but crashes in Android. What is the proper cross-platform way to do this?
// TODO get from service or xml
var path = AppDomain.CurrentDomain.BaseDirectory;
//var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
var fullpath = Path.Combine(path, "Services\\questions.json");
var json = File.ReadAllText(fullpath);
MAUI has a new way to access files included with the app: MauiAsset.
Described in blog Announcing .NET MAUI Preview 4, Raw Assets:
.NET MAUI now makes it very easy to add other assets to your project and reference them directly while retaining platform-native performance. For example, if you want to display a static HTML file in a WebView you can add the file to your project and annotate it as a MauiAsset in the properties.
<MauiAsset Include="Resources\Raw\index.html" />
Tip: you can also use wildcards to enable all files in a directory:
... Include="Resources\Raw\*" ...
Then you can use it in your application by filename.
<WebView Source="index.html" />
UPDATE
However, the feature MauiAsset apparently still needs improvement:
open issue - MauiAsset is very hard to use.
There we learn that for now:
Set BuildAction in each file's properties to MauiAsset.
That is, its not recommended to use the "wildcard" approach at this time. Set that build action on each file in solution explorer / your project / the file.
Accessing on Windows requires a work-around:
#if WINDOWS
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif
NOTE: This will be simplified at some point; follow that issue to see progress.
UPDATE
The current MAUI template is missing some platform-specific flags. For now, add your own flag to identify when the code is running on Windows:
Complete example in ToolmakerSteve - repo MauiSOAnswers. See MauiAssetPage.
MauiAssetPage.xaml:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiTests.MauiAssetPage">
<ContentPage.Content>
<!-- By the time Maui is released, this is all you will need. -->
<!-- The Init code-behind won't be needed. -->
<WebView x:Name="MyWebView" Source="TestWeb.html" />
</ContentPage.Content>
</ContentPage>
MauiAssetPage.xaml.cs:
using Microsoft.Maui.Controls;
using System.Threading.Tasks;
namespace MauiTests
{
public partial class MauiAssetPage : ContentPage
{
public MauiAssetPage()
{
InitializeComponent();
Device.BeginInvokeOnMainThread(async () =>
{
await InitAsync();
});
}
private async Task InitAsync()
{
string filePath = "TestWeb.html";
#if WINDOWS
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif
if (stream != null)
{
string s = (new System.IO.StreamReader(stream)).ReadToEnd();
this.MyWebView.Source = new HtmlWebViewSource { Html = s };
}
}
}
}
TestWeb.html:
(whatever html you want)
In Solution Explorer, add TestWeb.html to your project. In its Properties, select Build Action = MauiAsset.
I tried looking for a solution to this for months. I ended up hosting the file online then creating a method to download the file during runtime
public async Task DownloadFile(string fileName)
{
if (File.Exists(FileSystem.Current.AppDataDirectory + $"/{fileName}"))
{
return;
}
else
{
try
{
NetworkAccess networkAccess = Connectivity.Current.NetworkAccess;
if (networkAccess == NetworkAccess.Internet)
{
await Task.Run(() =>
{
var uri = new Uri($"https://myhostedfile.com/{fileName}");
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCallback2);//checking if download is complete
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(MaintainProgress);//event handler to check download progress
webClient.DownloadFileAsync(uri, FileSystem.Current.AppDataDirectory + $"/{fileName}");
});
}
else
await Shell.Current.DisplayAlert("No Internet", "Failed to get some files from the internet, confirm if your internet is" +
"working", "OK");
}
catch (Exception)
{
await Shell.Current.DisplayAlert("Error", "Failed to get some files from the internet, confirm if your internet is" +
"working", "OK");
}
}
}
Then you can access your file URL using:
string filePath = FileSystem.Current.AppDataDirectory + $"/myfile.pdf;
Using Xamarin.Forms, has the way to write to file changed since Android 8.0?
I updated an existing project of mine, which includes a very simple function to write a text file to local storage, but after running the app and testing the write to file part, it just freezes and crashes out. There are no errors in the console or even evidence of it doing anything.
My function is as such:
public void Submit_Clicked(object sender, EventArgs e)
{
{
string text = NameEntry.Text;
string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string filename = Path.Combine(path, "DeviceProfile.txt");
File.WriteAllText(filename, text);
}
catch(Exception ex)
{
DisplayAlert("Error:", ex.Message.ToString(), "Ok");
}
}
I cant see why this shouldn't work. Does someone know any reason why this wouldn't?
Like Jason said, the code below and the code you provided both work to write a text file to local storage.
string text = NameEntry.Text;
var path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "DeviceProfile.txt");
using (var writer = File.CreateText(backingFile))
{
await writer.WriteLineAsync(text);
}
You could read the text from the file to check.
public async Task<string> ReadCountAsync()
{
var backingFile = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "DeviceProfile.txt");
if (backingFile == null || !File.Exists(backingFile))
{
return null;
}
var text = string.Empty;
using (var reader = new StreamReader(backingFile, true))
{
var str = await reader.ReadToEndAsync();
text = str;
}
return text;
}
The path Environment.SpecialFolder.Personal you used to save the file is internal storage.
In Internal Storage, you couldn't see the files without root permission. If you want to view it, you could use adb tool. Please check the way in link.
How to write the username in a local txt file when login success and check on file for next login?
Hy, I'm working in a Xamarin PCL project with the platforms Android and UWP. As a feature the user should be able to open an pdf file.
For this I'm using Mozilla pdf.js. I have followed this link to get it done on Android and UWP.
https://developer.xamarin.com/recipes/cross-platform/xamarin-forms/controls/display-pdf/
Only for UWP I can't get it to function.
Here is my custom renderer for UWP
[assembly: ExportRenderer(typeof(PdfView),
typeof(PDF.UWP.Renderers.PdfViewRenderer))]
namespace PDF.UWP.Renderers
{
/// <summary>
/// The asset folder of the UWP app must contain the pdfjs folder and files.
/// </summary>
public class PdfViewRenderer: WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
PdfView pdfView = Element as PdfView;
string sFile = string.Format("ms-appx-web://{0}", WebUtility.UrlEncode(pdfView.Uri));
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", sFile));
}
}
}
}
Here is my PdfView class.
public class PdfView: WebView
{
public static readonly BindableProperty DocumentInfoProperty =
BindableProperty.Create(propertyName: nameof(TheDocumentInfo), returnType: typeof(DocumentInfo),
declaringType: typeof(PdfView), defaultValue: default(DocumentInfo));
public DocumentInfo TheDocumentInfo
{
get { return (DocumentInfo)GetValue(DocumentInfoProperty); }
set { SetValue(DocumentInfoProperty, value); }
}
public string Uri { get { return TheDocumentInfo.LocalUrl; } }
public string FileName { get { return TheDocumentInfo.FileName; } }
}
The file location on uwp =
"ms-appx-web://C%3A%5CUsers%5CUser%5CAppData%5CLocal%5CPackages%5CPDFTEST.UWP_v4j5n0js0cwst%5CLocalState%5CPDFTest.pdf"
And this is correct.
But the error is:
Message: Unexpected server response (0) while retrieving PDF
"ms-appx-web://C:/Users/User/AppData/Local/Packages/PDFTest.UWP_v4j5n0js0cwst/LocalState/PDFTest.pdf/".
UPDATE
I have recreated the renderer to:
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
// TODO: testen
PdfView pdfView = Element as PdfView;
string sFile = string.Format("ms-appx-web://{0}/{1}", pdfView.Uri.Replace(pdfView.FileName, ""), WebUtility.UrlEncode(pdfView.FileName));
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", sFile));
}
}
I don't know if this is the solution to my problem but this error is gone.
The error now is:
PDF.js v1.1.366 (build: 9e9df56)
Message: stream must have data
UPDATE (I don't know if u should add this in this question or if I should made another one).
My error is still
stream must have data
I know now why. Because I'm developing a UWP application and I want to access a file outside my instal folder. This location is
C:\Users\User\AppData\Local\Packages\PDFTest.UWP_v4j5n0js0cwst\LocalState\
Apperently I can't access files outside my instalation folder. This includes coping the file to my install folder and read it there.
UPDATE
I have 2 versions of pdf.js in my project. (1.1.366 and 1.9.426)
This is my code now
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
PdfView pdfView = Element as PdfView;
var uriString = "ms-appdata:///local/" + WebUtility.UrlEncode(pdfView.FileName);
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html?file={0}", uriString));
}
}
When I try to open the file with Launcher.LaunchFileAsync and use the uriString it opens my browser and shows me the file.
In my application I get the following error's
(v1.1.366) Stream must have data.
(v1.9.426) Unexpected server response (0) while retrieving PDF "ms-appdata:///local/PDFTest.pdf".
I know that the pdf uri is correct and accessible but it still doesn't work.
(for v1.9.426 I have added in viewer.js
var HOSTED_VIEWER_ORIGINS = ['null', 'http://mozilla.github.io', 'https://mozilla.github.io', 'ms-appdata://', 'ms-appx-web://PDFTest.uwp'];)
link to the testproject
I know now why. Because I'm developing a UWP application and I want to access a file outside my instal folder. This location is
You have use ms-appx-web: uri scheme as your pdf file access path. Actually, your pdf path is C:\Users\User\AppData\Local\Packages\PDFTest.UWP_v4j5n0js0cwst\LocalState\ that stored in the app's local folder. So the file will not be accessed.
I have also tested with "ms-appdata:///local/" uri scheme to access the pdf file base on your project. Unfortunately, It can't be recognised by viewer.js.
And then, I tried to convert pdf file into Base64String then opening it by calling the openPdfAsBase64 JS function in the viewer.js.
private async Task<string> OpenAndConvert(string FileName)
{
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync(FileName);
var filebuffer = await file.OpenAsync(FileAccessMode.Read);
var reader = new DataReader(filebuffer.GetInputStreamAt(0));
var bytes = new byte[filebuffer.Size];
await reader.LoadAsync((uint)filebuffer.Size);
reader.ReadBytes(bytes);
return Convert.ToBase64String(bytes);
}
Usage
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
Control.Source = new Uri("ms-appx-web:///Assets/pdfjs3/web/viewer.html");
Control.LoadCompleted += Control_LoadCompleted;
}
}
private async void Control_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
CustomWebView pdfView = Element as CustomWebView;
if (string.IsNullOrEmpty(pdfView?.Filename)) return;
var ret = await OpenAndConvert(pdfView?.Filename);
var obj = await Control.InvokeScriptAsync("openPdfAsBase64", new[] { ret });
}
You could use this viewer.js that was added openPdfAsBase64 method.
Got hints following: How to embed the PDFjs into your C# Project.
I have been trying to download and load the texture or other models from a WEB at run time by using WWW class.
The app works well on Unity Editor but when I deploy it on android device it doesn't load/download the texture.
Please somebody guide me.
I have used the following code in script.
void Start()
{
StartCoroutine(loadMovie());
}
IEnumerator loadTexture()
{
WWW www = new WWW("http://images.earthcam.com/ec_metros/ourcams/fridays.jpg");
yield return www;
// Debug.Log(www.movie.duration + " <--- wwww");
if (www.error != null)
{
Debug.Log("Error: Can't load texture! - " + www.error);
yield break;
}
else
{
Texture2D texture = www.texture as Texture2D;
Debug.Log("Texture loaded");
Debug.Log(www.texture);
gameObject.GetComponent<Renderer>().material.mainTexture = texture;
}
}
First of all, remove Debug.Log(www.texture); from the code, then re-try your code.
You have IEnumerator loadTexture() but you are calling StartCoroutine(loadMovie()); . This means that you are likely calling another function or maybe that's a type in your question.
void Start()
{
StartCoroutine(loadTexture());
}
IEnumerator loadTexture()
{
WWW www = new WWW("http://images.earthcam.com/ec_metros/ourcams/fridays.jpg");
//Wait for download to finish
while(!www.isDone){
Debug.Log("Progress: "+www.progress);
yield return null;
}
if ((www==null) || (www.error != null))
{
Debug.Log("Error: Can't load texture! - " + www.error);
yield break;
}
gameObject.GetComponent<Renderer>().material.mainTexture = www.texture;
}
Not compiled but should work.
EDIT:
From the file you sent, change the Minimum API Level to 4.1.