How to implement a system which takes the best texture based on dpi from a set like in android SDK, because LibGDX is platform independent, and can't use the already existent one?
May be my solution is not the best but I used it in real project and it worked.
In your Game class use Gdx.graphics.getDensity() method to choose appropriate folder, store its name in public field and load your assets:
public class MyGame extends Game {
public static String folder;
private AssetManager assets;
#Override
public void create() {
if (Gdx.graphics.getDensity < 1) {
folder = "lowDpiImages/";
} else {
folder = "highDpiImages/";
}
...
assets = new AssetManager();
assets.load(folder + "image.png", Texture.class, paramsNearest);
...
}
Then in you other classes use folder name to get assets from AssetManager:
assets.get(MyGame.folder + "image.png", Texture.class);
You can write more sophisticated folder choosing algorithm of cause ;-)
Related
Working with Weex 0.16 I generated the default "WeexDemo" project for Web, iOS and Android, and the default index files works without issue.
I'm trying to figure out the folder location where I can put image files and other assets. I changed the "logoUrl" from an http url to a relative path ('bg.png')
Serving on the browser over 8080 port web root is the project root folder, so if I copy bg.png to "dist" folder I can see it when logoUrl is "/dist/bg.png"
On the iOS project "/dist/bg.png" does not work, since the root seems to be the "dist" folder itself, if I change to logoUrl "bg.png", it works.
On the Android project, both "/dist/bg.png" or "bg.png" fail. I can see in the folder "/platforms/android/app/src/main/assets/dist" the bg.png file has been copied but I don't seem to able to access it.
Is there any solution where I can use the same folder to drop the assets and have it accessible for all devices?
Do as follows :
In your application class :
WXSDKEngine.registerComponent("yourImage", YourImage.class);
create class YourImage.java and it should look like this :
public class YourImage extends WXComponent<ImageView> {
public YourImage(WXSDKInstance instance, WXDomObject dom, WXVContainer parent) {
super(instance, dom, parent);
}
#Override
protected ImageView initComponentHostView(#NonNull Context context) {
ImageView imageView = new ImageView(context);
return imageView;
}
#WXComponentProp(name = Constants.Name.SRC)
public void setSrc(String src) {
if (src == null) {
return;
}
if(null != getHostView()) {
Picasso.with(WXEnvironment.getApplication()).load(src).into(getHostView());
}
}
}
In your vue/js file
<yourImage class="image" :src="url"> </yourImage>
In your WeexUIFragment/Activity : while loading page data through map, add one key and value as follows:
HashMap<String, Object> map = new HashMap<>();
map.add("image_url", "android local asset url")
map.put("PAGENAME", "");
mWXSDKInstance = new WXSDKInstance(YourCurrentActivity.this);
mWXSDKInstance.registerRenderListener(YourCurrentActivity.this);
mWXSDKInstance.render(pageName, weexJSUrl, map, null, WXRenderStrategy.APPEND_ASYNC);
In JS file in script/data block to retrieve asset local image url:
const url = _.get(weex,'config.image_url')
If you need more help: You can look into Component Extend section in below link :
https://weex.incubator.apache.org/guide/extend-android.html
So in my app i pass a game object, called datacontroller through out my three scenes. The persistent scene is an empty scene, the menuscreen scene and then the game scene. My application works perfectly on my computer and in editor mode but when i download the apk to my android tablet it no longer works! iv'e read this may have to do with my code for my object but i dont think i written anything that only works in the editor.
enter code here
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
using System.IO; // The System.IO namespace contains functions related to loading and saving
files
public class DataController : MonoBehaviour
{
private RoundData[] allRoundData;
private PlayerProgress playerProgress;
private string gameDataFileName = "data.json";
void Start()
{
DontDestroyOnLoad(gameObject);
LoadGameData();
LoadPlayerProgress();
SceneManager.LoadScene("MenuScreen");
}
public RoundData GetCurrentRoundData()
{
// If we wanted to return different rounds, we could do that here
// We could store an int representing the current round index in PlayerProgress
return allRoundData[0];
}
public void SubmitNewPlayerScore(int newScore)
{
// If newScore is greater than playerProgress.highestScore, update playerProgress with the new value and call SavePlayerProgress()
if (newScore > playerProgress.highestScore)
{
playerProgress.highestScore = newScore;
SavePlayerProgress();
}
}
public int GetHighestPlayerScore()
{
return playerProgress.highestScore;
}
private void LoadGameData()
{
// Path.Combine combines strings into a file path
// Application.StreamingAssets points to Assets/StreamingAssets in the Editor, and the StreamingAssets folder in a build
string filePath = Path.Combine(Application.streamingAssetsPath, gameDataFileName);
if (File.Exists(filePath))
{
// Read the json from the file into a string
string dataAsJson = File.ReadAllText(filePath);
// Pass the json to JsonUtility, and tell it to create a GameData object from it
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
// Retrieve the allRoundData property of loadedData
allRoundData = loadedData.allRoundData;
}
else
{
Debug.LogError("Cannot load game data!");
}
}
// This function could be extended easily to handle any additional data we wanted to store in our PlayerProgress object
private void LoadPlayerProgress()
{
// Create a new PlayerProgress object
playerProgress = new PlayerProgress();
// If PlayerPrefs contains a key called "highestScore", set the value of playerProgress.highestScore using the value associated with that key
if (PlayerPrefs.HasKey("highestScore"))
{
playerProgress.highestScore = PlayerPrefs.GetInt("highestScore");
}
}
// This function could be extended easily to handle any additional data we wanted to store in our PlayerProgress object
private void SavePlayerProgress()
{
// Save the value playerProgress.highestScore to PlayerPrefs, with a key of "highestScore"
PlayerPrefs.SetInt("highestScore", playerProgress.highestScore);
}
}
I am starting to go through tutorials of unity myself so I am not an expert. :)
But what I would try is the first thing. using System.IO; not sure if this will work to get files on android because android has a different file structure. So I would first remove it and sort of hard code the file path or comment out the code using System.IO classes then recompile apk in unity and check if it works. I also saw this post : http://answers.unity3d.com/questions/1023391/systemio-dont-work-on-android.html
If that did not work I would comment functionality out and compile apk and check if its working if its not comment more code out until you find the line or the code that causes it to error on android. This method takes long to troubleshoot or get your code causing the problem but for me this has worked before.
I am guessing as it is working on you pc its a class or something its referencing that's not available in android.
Please share your findings if you figure out what part of the code does it. As I would also want to know to prevent me from doing it. :)
Avoid the use of System.IO on Android and in general on Unity.
Use "Resources" instead, just following this steps:
Create a folder called "Resources"
Move json file on it and rename in .txt
Use this code to get the string:
var file = Resources.Load("filename_here") as TextAsset;
Debug.Log(file.text)
I have a Xamarin Forms project in which I need the user to be able to "load" an image. I can already press a button and search for a file using FilePicker like this:
async void OnUpload(object sender, EventArgs e)
{
try
{
FileData filedata = await CrossFilePicker.Current.PickFile();
// the dataarray of the file will be found in filedata.DataArray
// file name will be found in filedata.FileName;
//etc etc.
}
catch (Exception ex)
{
}
}
What I would need now is to copy that "filedata" (the image) to the resource folder of the project in order to access to the file easily. I have tried:
await CrossFilePicker.Current.SaveFile(filedata.FileName);
but it doesn't save any file into the project folder.
Moreover, I only need it to work on UWP and Android.
The SaveFile method saves it in a very specific folder.
If you want to save it somewhere of your choosing you have to implement it with the DependencyService. IO operations are very specific to the OS, so are the filepaths. I will give you a simple example for you to build on.
Start with defining an interface in your shared code, like so:
public interface IFileManager
{
void SaveFile(Stream stream);
}
Of course, it can have other methods as well, or extra parameters if you would like to specify things like filename, that is up to you. You would also probably like some kind of return value to know what happened.
Now, per platform implement this interface. For example for Android, it could look like this:
[assembly: Xamarin.Forms.Dependency (typeof (FileManager_Android))]
public class FileManager_Android : IFileManager
{
public void SaveFile(Stream stream)
{
var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim);
string filename = System.DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
string filePath = System.IO.Path.Combine(dir, name);
try
{
System.IO.File.WriteAllBytes(filePath, imageData);
}
catch (Exception ex)
{
System.Console.WriteLine(e.ToString());
}
}
}
(Saving code inspired by this link)
This will take the stream and save it to a path of your choosing.
For UWP you will need to implement it as well, which is quite similar, except for the implementation of SaveFile. As far as I know there is no plugin yet which makes this easier for you. There is PCLStorage, but this plugin only seems to work with text files. You could still look into it for inspiration though.
I've read every SO post regarding use of fonts in Android and I still can't get mine to work. I'm getting the following exception:
java.lang.RuntimeException: native typeface cannot be made
Here's my code (this class and static method is taken from here):
public class SafeTypefaces {
private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();
public static Typeface get(Context c) {
final String assetPath = "fonts/robotobold.ttf";
synchronized (cache) {
if (!cache.containsKey(assetPath)) {
try {
AssetManager assetManager = c.getAssets();
Typeface t = Typeface.createFromAsset(assetManager, assetPath); //Throws exception on this line!
cache.put(assetPath, t);
} catch (Exception e) {
L.p("Could not get typeface '" + assetPath + "' because " + e.getMessage());
return null;
}
}
return cache.get(assetPath);
}
}
}
The font is in the assets/fonts folder:
(this is still Eclipse. I know, I know).
Things I've tried:
I've tried moving the font to the root of the assets folder and updating the assetPath.
I checked folder and file permissions.
I tried using the application context instead of the activity context I'm getting.
I tried using different font files (one send via email, another downloaded from the Internet).
As I was creating this question I ran into the solution. I've spend a few hours on this so I guess its worth keeping.
My problem was that I was working on a library project. According to this (Android Library assets folder doesn't get copied), assets in library projects aren't available to the main project, which is why the font file wasn't being found. (Again, this project is still using Eclipse. Possibly not the case using Gradle+AS).
The solution is to copy the fonts into the main project, and voila!
I am trying to build an augmented reality app and in that app i want some prefabs to load dynamically. So that with some 3d model prefabs on unity store i created myasset.unity3d . I am using WWW.LoadFromCacheOrDownload to download that unity3d file and using it.
When i am debugging in my laptop the file is downloading and i am using it as i want but when i add build in and try it on android phone download is not happening.
The code i am using to download is
IEnumerator DownloadAndCache() {
while (!Caching.ready)
yield return null;
string bundleURL = "http://s3-ap-southeast-1.amazonaws.com/cf-export/sofa.unity3d";
www = WWW.LoadFromCacheOrDownload (bundleURL, 1);
yield return www;
Debug.Log (www.assetBundle);
AssetBundle bundle = www.assetBundle;
}
So please help me .
i also tried other way of doing it but still i did not succeed
IEnumerator Start () {
WWW www = WWW.LoadFromCacheOrDownload (BundleURL, 1);
yield return www;
AssetBundle bundle = www.assetBundle;
AssetBundleRequest request = bundle.LoadAssetAsync (AssetName, typeof(GameObject));
yield return request;
GameObject obj = request.asset as GameObject;
Instantiate (obj);
bundle.Unload(false);
www.Dispose();
}
The above two methods are working in when testing in unity IDE but if i build using android and install it in android device its not working. I gave internet access to app while building
I printed the error using a text in mobile and please check the screen shot attached below
the first error text is www (variable for downloading) and second is www.error ( actual error). i did not get what that error meant. So please help me
the issue is asset bundle version is not sync with app version. So while making asset bundle i added small code which made my code working. To make Asset bundle my code is
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem ("Assets/Build AssetBundles")]
static void BuildAllAssetBundles ()
{
BuildPipeline.BuildAssetBundles ("Assets/AssetBundles", BuildAssetBundleOptions.None, BuildTarget.Android);
}
}
To use AssetBuundle for Mobile platform:
While creating AssetBundle it must be platform specific. For Android use following Script to create AssetBundle. put it inside "Editor"
using UnityEngine;
using System.Collections;
using UnityEditor;
public class ExportAssetBundles : Editor {
[MenuItem("Assets/Build AssetBundle")]
static void ExportResource()
{
string path = "Assets/AssetBundle/myAssetBundle.unity3d";
Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path,
BuildAssetBundleOptions.CollectDependencies
| BuildAssetBundleOptions.CompleteAssets,BuildTarget.Android);
}
}
Then Create folder "AssetBundle" inside Asset
When you create Assetbundle the AssetBundle.unity3d file will store inside this folder
Now you need to use Created Assetbundle at runtime. For this,
Write a script AssetBundleAugmenter
public class AssetBundleAugmenter : MonoBehaviour {
public string AssetName;
public int Version;
private GameObject mBundleInstance = null;
private bool mAttached = false;
void Start() {
StartCoroutine(DownloadAndCache());
}
// Update is called once per frame
IEnumerator DownloadAndCache() {
while(!Caching.ready)
yield return null;
//you can use remote URL like: www.arprabhu.com/assetBundle OR Local URL
// example URL of file on PC filesystem (Windows)
// string bundleURL = "file:///D:/Unity/AssetBundles/MyAssetBundle.unity3d";
// example URL of file on Android device SD-card
string bundleURL = System.IO.File.ReadAllText("/mnt/sdcard/filepath.txt");
Debug.Log ("Asset Loaded");
using (WWW www = WWW .LoadFromCacheOrDownload(bundleURL, Version)) {
yield return www;
if (www .error != null)
throw new UnityException("WWW Download had an error: " + www .error);
AssetBundle bundle = www .assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
Instantiate(bundle.LoadAsset(AssetName));
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
}
}}
Attach this Script to Empty GameObject in your Scene
Congrats!, you are ready to go.
Try checking your androidManifest.xml for the permission to connect to external servers.
Then, if everything seems alright and still doesn't work, my advice is to download the Device Console plugin for the Unity Editor, which is a really nice way to access the internal Android Debugger.
https://www.assetstore.unity3d.com/en/#!/content/44935
Or if you're truly brave: use logcat within the terminal...