zoukankan      html  css  js  c++  java
  • Unity头像上传功能实现 一(接在《Unity调用Andriod相册,细节分享》后)

    来源:https://blog.csdn.net/cscscs007/article/details/79633004

    2018-06-01 后面由于要接入微信登录/支付、支付宝支付这些东西,原来在MainActivity中实现这些逻辑明显不太好了,于是将这个类重新整理了一下,方便后续添加其他接口
    GitHub地址: https://github.com/alexchenc/unityplugins

    前段时间需要做一个头像上传功能,参考了一些资料后总算是弄了出来。
    首先感谢其他博主们的分享:
    Unity3D研究院之打开照相机与本地相册进行裁剪显示(三十三)
    Unity3d本地上传并且裁剪图片—–Android平台

    1. 新建安卓项目
    新建一个Android项目,我这里用的是Idea(Eclipse的安卓插件一直弄不好然后放弃了),第一次建要好长时间下载插件,耐心等一下。
    Application name: 自己随意命名一个。
    Company Domain: 也是自己命名。
    Package name: 点击右边Edit,自己修改包名。此处包名需要和Unity项目中打包的包名相同
    1
    2
    3


    这是Unity项目中的设置。包名与AndroidAPI版本


    下一步,选择最低版本API。版本越低兼容越好,这里我选的是4.1,与Unity中保持的一致。


    下一步,创建Activity。只需要创建一个空的Activity即可,选择EmptyActivity。

    这个Activity就命名为MainActivity吧,勾选“Generate Layout File”,生成Layout文件;
    不用勾选下面那个框,点击Finish创建完成。

    2. Unity环境集成
    首先需要把Unity的jar包拷贝过来,放在libs目录下。jar包在Unity软件目录下找:

    /Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/mono/Release/Classes/classes.jar


    如果找不到就用Spotlight搜索 classes.jar,去与Unity有关的路径查找。
    将jar包拷贝至libs目录下,右键->Add as Library, 确定,导入jar包。

    3. 打开相册和相机,裁剪功能实现
    让MainActivity继承自UnityPlayerActivity(从Unity导入的jar包中包含的类)
    这个MainActivity将作为App启动的第一个Activity
    由于后期可能需要接入多个Api,所以只把这里当做一个Controller,具体逻辑放在各自的类中实现。这里我将相机、相册逻辑放在PhotoService.java中。
    MainActivity.java代码如下:
    package com.cclovers.demo;

    import android.content.Intent;
    import android.os.Bundle;
    import com.unity3d.player.UnityPlayerActivity;

    public class MainActivity extends UnityPlayerActivity {

    public static final String UNITY_GAMEOBJECT = "AndroidManager";

    public static MainActivity Instance;

    @Override
    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    //直接打包apk时需要设置下面这一行
    // setContentView(R.layout.activity_main);
    Instance = this;
    }

    /**
    * 调用相机
    */
    public void openCamera() {
    PhotoService.GetInstance().openCamera();
    }

    /**
    * 调用相册
    */
    public void openAlbum() {
    PhotoService.GetInstance().openAlbum();
    }

    /**
    * 调用支付宝API
    */
    public void openAlipay(String orderStr) {
    }

    /**
    * 调用微信API
    */
    public void openWechat() {

    }

    /**
    * 微信登录接口
    */
    public void openWechatLogin() {
    }

    /**
    * 回调
    * @param requestCode
    * @param resultCode
    * @param data
    */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    //调用相机/相册的返回结果
    PhotoService.GetInstance().onActivityResult(requestCode, resultCode, data);
    }

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    PhotoService.java 用来处理相机、相册逻辑,使用的单例模式。
    代码如下:
    package com.cclovers.demo;

    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Environment;
    import android.provider.MediaStore;
    import com.unity3d.player.UnityPlayer;

    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;

    public class PhotoService {

    private static final int NONE = 0;
    private static final int ALBUM = 1; //相册
    private static final int CAMERA = 2; //拍照
    private static final int RESULT = 3; //结果

    public static final String IMAGE_UNSPECIFIED = "image/*";
    public final static String PHOTO_NAME = "temp.jpg";
    public final static String CROP_NAME = "temp.png";
    public final static String PERSISTANT_PATH = "/Android/data/com.cclovers.demo/files/images/";

    private PhotoService() {
    // 1. 根目录 Environment.getExternalStorageDirectory() = storage/emulated/0
    photoPath = Environment.getExternalStorageDirectory().toString() + "/" + PHOTO_NAME;
    // 2. 程序读写目录Applicatio.persistantDataPath = /Android/data/com.xxx.xxx/files/
    cropPath = Environment.getExternalStorageDirectory().getAbsolutePath() + PERSISTANT_PATH;
    }

    private static PhotoService instance;

    public static PhotoService GetInstance() {
    if (instance == null) {
    instance = new PhotoService();
    }
    return instance;
    }

    public static boolean HasInstance() {
    return instance != null;
    }

    private String photoPath; //相机拍照图片路径
    private String cropPath; //裁剪结果路径

    /**
    * 调用相机
    */
    public void openCamera() {
    try {
    File file = new File(photoPath);
    //先删除该文件再创建
    if (file.exists()) {
    file.delete();
    }

    //图片路径
    Uri imageUrl = Uri.fromFile(file);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUrl);
    MainActivity.Instance.startActivityForResult(intent, CAMERA);
    } catch (Exception ex) {
    LogUtil.logError(ex.getMessage());
    }
    }

    /**
    * 调用相册
    */
    public void openAlbum() {
    Intent intent = new Intent(Intent.ACTION_PICK, null);
    intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED);
    MainActivity.Instance.startActivityForResult(intent, ALBUM);
    }

    /**
    * 调用裁剪
    *
    * @param uri
    */
    public void startPhotoZoom(Uri uri) {
    Intent intent = new Intent("com.android.camera.action.CROP");

    intent.setDataAndType(uri, IMAGE_UNSPECIFIED);
    intent.putExtra("crop", "true");
    // aspectX aspectY 是宽高的比例
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    // outputX outputY 是裁剪图片宽高
    intent.putExtra("outputX", 100);
    intent.putExtra("outputY", 100);
    intent.putExtra("return-data", true);

    MainActivity.Instance.startActivityForResult(intent, RESULT);
    }

    /**
    * 将裁剪结果保存到本地(只能是Unity具有访问权限的路径)
    */
    public void SaveBitmap(Bitmap bitmap) throws IOException {

    FileOutputStream stream = null;
    try {
    if (bitmap != null) {
    //检查路径是否存在,如果没有则创建
    File destDir = new File(cropPath);
    if (!destDir.exists()) {
    destDir.mkdirs();
    }

    //获取文件流
    stream = new FileOutputStream(cropPath + CROP_NAME);

    //写入本地
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    stream.flush();
    }
    } catch (Exception e) {
    LogUtil.logError(e.getMessage());
    } finally {
    if (stream != null) {
    stream.close();
    }
    }
    }

    /**
    * 回调
    * @param requestCode
    * @param resultCode
    * @param data
    */
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    try {

    //相册
    if (requestCode == ALBUM) {
    if (data != null) {
    //跳转到裁剪
    Uri uri = data.getData();
    if (uri != null) {
    startPhotoZoom(uri);
    }
    }
    }
    //相机
    else if (requestCode == CAMERA) {
    File file = new File(photoPath);
    if (file != null && file.exists()) {
    //跳转到裁剪
    Uri uri = Uri.fromFile(file);
    if (uri != null) {
    startPhotoZoom(uri);
    }
    }
    }
    //裁剪结果
    else if (requestCode == RESULT) {
    if (data != null) {
    Bundle extras = data.getExtras();
    if (extras != null) {
    Bitmap photo = extras.getParcelable("data");
    if (photo != null) {
    SaveBitmap(photo);
    //调用unity中方法 GetImage
    UnityPlayer.UnitySendMessage(MainActivity.UNITY_GAMEOBJECT, "GetImage", CROP_NAME);
    }
    }
    }
    }
    } catch (Exception e) {
    LogUtil.logError("Error:" + e.getMessage());
    }
    }

    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    工具类 LogUtil.java, 用于向Unity发送log信息:
    package com.cclovers.demo;

    import com.unity3d.player.UnityPlayer;

    /**
    * Created by Alex on 18/5/30.
    */
    public class LogUtil {

    public static void logError(String message) {
    try {
    UnityPlayer.UnitySendMessage(MainActivity.UNITY_GAMEOBJECT, "LogError", message);
    }
    catch (Exception e) {
    }
    }

    public static void logDebug(String message) {
    try {
    UnityPlayer.UnitySendMessage(MainActivity.UNITY_GAMEOBJECT, "LogDebug", message);
    }
    catch (Exception e) {
    }
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    3. 小结
    核心功能其实就在PhotoService中了,具体实现也没有什么逻辑,大多是控制跳转
    稍微需要注意一下的可能是图片储存的路径了,Unity程序的文件夹权限只有根据包名生成的文件夹下,所以图片只能存在在这里,然后在Unity中去读取这个图片
    4. android项目打包配置,导出jar包和资源
    设置AndroidManifest.xml
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cclovers.demo">

    <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
    android:name="com.cclovers.demo.MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    </activity>
    </application>

    <!-- 连接互联网的权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- SDCard中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!-- SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    </manifest>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    导出jar包了,Idea需要设置一下才能导出jar包,File->Project Structure->Artifacts

    如果输出文件中有与class.jar 和 res有关的文件,就全部去掉吧,只留一个app的。不然在Unity打包apk的时候会失败,原因是插件资源重复,具体错误代码就不贴了。

    勾选中Include in project build, 在项目build的时候就会生成jar包了,然后到输出目录去找.

    这里的jar包还要再处理一下,用压缩软件打开
    - 删除所有以**R$**开头的文件
    - 将**BuildConfig.class**删除掉
    - 删除Android文件夹(如果有)
    - 只留下自己眼熟的文件,如图,然后保存-_-。
    1
    2
    3
    4


    需要注意的是,由于API版本的原因,有些地方可能会导致在Unity中打包失败,具体原因可根据错误代码去搜索一下。
    以下是我遇到的问题,打包报错安卓主题找不到,解决办法如下:
    需要修改一下src/res/values/styles.xml
    <resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    </style>

    **改为下面**

    <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="android:colorPrimary">@color/colorPrimary</item>
    <item name="android:colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="android:colorAccent">@color/colorAccent</item>
    </style>
    </resources>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    5. 导入到Unity
    最后就是导入到Unity中集成了,在Unity项目中新建目录:Assets/Plugins/Android
    新建bin目录,将导出的jar包拷入其中;
    把res文件从android项目全部拷贝过来
    AndroidManifest.xml拷贝至Android目录下
    项目结构如下:

    5. 总结
    以上就是头像上传功能java部分的实现了,看起来内容不多,但实际操作起来还是会遇到许多问题的,一边参考其他的资料一边尝试,花了几天的时间才把这些问题解决。
    至于后面在Unity中如何使用和读取图片功能,等有时间再写一下
    ————————————————
    版权声明:本文为CSDN博主「丶淺忆」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/cscscs007/article/details/79633004

  • 相关阅读:
    SAP BW 例程(Routine)【开始例程、关键值或特性的例程、结束例程】
    sap 提取字符串中汉字
    判断当前一个物料被其他人锁定
    ABAP "FOR ALL ENTRIES IN" 使用指南
    ABAP检查日期and时间合法性的函数
    READ语句相关
    QUERY客户出口变量的I_STEP解释
    Abap 内表的语法
    Ancient Knight(打造Windows Mobile平台最专业的游戏修改器)
    VC通用控件自适应屏幕类
  • 原文地址:https://www.cnblogs.com/LiTZen/p/11899036.html
Copyright © 2011-2022 走看看