Cross-device local assets location in Weex - android

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

Related

Copy image to resources Xamarin

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.

Load SVG file in Xamarin with SkiaSharp

From release 1.55.0 SkiaSharp has the support for reading SVG files.
The package has been release few days ago (10 Nov. 2016) and I couldn't find enough documentation on how to use it.
The following packages are required:
SkiaSharp 1.55.0
SkiaSharp Views & Layers 1.55.0
SkiaSharp.Svg 1.55.0-beta1
The first question is what's the best way to load an SKSvg in Xamarin.Android?
Here two possible solutions to start working with SkiaSharp that are working for me:
Loading SVG from Asset folder (or subfolder):
public SKSvg LoadAnSvgFromAssets(Context ctx, string assetSvgFileLoc)
{
var assets = ctx.Assets;
var svg = new SKSvg();
using (var stream = new StreamReader(assets.Open(assetSvgFileLoc)))
{
svg.Load(stream.BaseStream);
return svg;
}
}
where "assetSvgFileLoc" is the svgFilename.svg to load, including (if it's the case) the path inside Asset folder (e.g. "subf1/subf2/mysvg.svg").
Loading SVG as RAW Resource
public SKSvg LoadAnSvgFromResources(Context ctx, string svgName))
{
var resId = ctx.Resources.GetIdentifier(svgName, "raw", ctx.PackageName);
var svg = new SKSvg();
using (var stream = ctx.Resources.OpenRawResource(resId))
{
svg.Load(stream);
return svg;
}
}
In this case the file is inside the Resources subfolder "raw" and the "svgName" is the filename of our svg without extension.
To complete the accepted answer, here is how to load the SKSvg from a URL.
SkiaSharp.Extended.Svg.SKSvg svg = new SkiaSharp.Extended.Svg.SKSvg();
using (WebClient client = new WebClient())
{
svg.Load(new MemoryStream(client.DownloadData(new Uri(ResourceUrl))));
}
I am using this code ,it works great. I can have the SVG in PCL , ios or Android folder
Just remember to include the Assembly in path
var assembly = this.GetType().GetTypeInfo().Assembly;
using (var s = assembly.GetManifestResourceStream("MyAssembly.Core.Hold.svg"))
{
if (s != null)
{
svg = new SKSvg();
svg.Load(s);
using (SKPaint paint = new SKPaint())
{
canvas.DrawPicture(svg.Picture, paint);
}
}
}

WWW.LoadFromCacheOrDownload is not working in augmented reality app on android phone using unity

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...

Add pre-cached images in apk file for use with Picasso or similar library

I am using Picasso for retrieving and showing images in my Android app. To avoid downloading all images over the network I am trying to add some images with the apk file, as sort of a pre-cached set of images. These images are stored in the assets folder and then copied to the Picasso cache folder on installation. This works as expected, but Picasso still download all images through the network and caches them as .0 and .1 files like this:
root#generic_x86:/data/data/com.my.app/files/images_cache #
ls
10.JPG
100.JPG
101.JPG
102.JPG
11.JPG
1f94664dec9a8c205b7dc50f8a6f3b79.0
1f94664dec9a8c205b7dc50f8a6f3b79.1
2.JPG
4621206beccad87a0fc01df2d080c644.0
4621206beccad87a0fc01df2d080c644.1
The *.JPG images are the ones I copied and the others are the Picasso cached images. Is there a way to make Picasso cache these images properly on installation?
If not, are there any other similar libraries that supports this kind of pre-caching?
Update: trying to cache from Assets folder
I tried making a small snippet that is run at first run of the app. The idea is to iterate the files in the given assets folder and fetch those images with Picasso. However, the below does not cache anything, although I end up in the onSuccess() method of the callback. The asset file names are correct. This is also verified by using the wrong folder name, which puts me in the onError() method of the callback.
I also tried loading it into a temporary ImageView, but it did do any difference.
public static boolean cacheImagesFromAssetsFolder(Context context)
{
boolean ok = false;
try
{
String[] images = context.getAssets().list("my_images");
for (String image : images)
{
Picasso.with(context).load("file:///android_asset/my_images/" + image).fetch(new Callback()
{
#Override
public void onSuccess()
{
// This is where I end up. Success, but nothing happens.
}
#Override
public void onError()
{
}
});
}
ok = true;
}
catch (Exception e)
{
e.printStackTrace();
}
return ok;
}
You could use File URI to request the Picasso to pick the image from your asset location instead of n/w.
Picasso.with(activity) //
.load(Uri.fromFile(file)) // Location of the image from asset folder
Update: How to use your own cache
import com.squareup.picasso.LruCache;
import com.squareup.picasso.Util;
LruCache imageCache = new LruCache(context);
Request request = Request.Builder(Uri.fromFile(asset_file), 0, null).build();
String cacheKey = Util.createKey(request, new StringBuilder());
imageCache.set(cacheKey, bitmap_object_of_asset_image);
Picasso.Builder(context)
.memoryCache(imageCache)
.build().load(asset_url).fetch(callback);

How to get screenshot saved path by Cocos2d-x on android

I use saveToFile method to save screenshot, and I check CCLOG, it shows /data/data/com.xxx.xxx/files/xxx.png
However, when I use Java to get this file, it says "No such file or directory"....
What can I do?
I had the same problem. Apparently, cocos2dx never creates the writable path directory so the screenshot doesn't get saved.
My solution was to, instead of calling CCRenderTexture::saveToFile, copy its implementation and manually save the file to a different path:
std::string MyClass::takeScreenshot(CCScene* scene) {
cocos2d::CCSize screenSize = cocos2d::CCDirector::sharedDirector()->getWinSize();
cocos2d::CCRenderTexture* tex = cocos2d::CCRenderTexture::create(screenSize.width, screenSize.height);
tex->setPosition(ccp(screenSize.width/2, screenSize.height/2));
//use a different dir than cocos default writable path
std::string filename = "/sdcard/Android/data/screenshot.png";
tex->begin();
scene->getParent()->visit();
cocos2d::CCImage* img = tex->newCCImage(true);
img->saveToFile(filename.c_str(), true);
CC_SAFE_DELETE(img);
tex->end();
return filename;
}
I also had the same problem. When I try renderTexture->saveToFile method, I can't submit path to java. No matter, I used getWritablePath() or set the path directly "/sdcard/Android/data/com.xxx.xxx/snapshot.jpg".
I try also to solve this problem on the advice of Facundo Olano. But CCImage compose only solid black image.
Finally I combine this two methods. First, I make an image by renderTexture->saveToFile:
void MyScene::pressFaceBook()
{
...
RenderTexture* renderTexture = RenderTexture::create(sharedImage->getBoundingBox().size.width, sharedImage->getBoundingBox().size.height, Texture2D::PixelFormat::RGBA8888);
renderTexture->begin();
sharedImage->visit();
renderTexture->end();
renderTexture->saveToFile("snapshot.jpg", Image::Format::JPG);
const std::string fullpath = FileUtils::getInstance()->getWritablePath() + "snapshot.jpg";
sharedImage->setVisible(false);
this->runAction(Sequence::create(DelayTime::create(2.0f),
CallFunc::create(std::bind(&MyScene::shareFaceBook, this, fullpath)),
NULL));
}
And then I use initWithImageFile with the transferred file name:
void MyScene::shareFaceBook(const std::string& outputFile)
{
const std::string joutputFile = "/sdcard/Android/data/com.xxx.xxx/snapshot.jpg";
cocos2d::Image* img = new Image;
img->initWithImageFile(fullpath);
img->saveToFile(joutputFile);
CC_SAFE_DELETE(img);
singleton->shareFaceBook(joutputFile);
}
A delay of 2 seconds is needed to capture the screenshot.
Of course, instead com.xxx.xxx you must substitute your app name.

Categories

Resources