9a8d3cecbba9675dL137">137 135
    }
138 136

139 137

140
    public void saveBitmap(Bitmap mBitmap) {
141
        String dir_path = Environment.getExternalStorageDirectory() + File.separator + "D1ev/";
142
        File directory = new File(dir_path);
143
        File f = new File(directory, "erweima.png");
144
        try {
145
            if (!directory.exists()) {
146
                directory.mkdir();//没有目录先创建目录
147
            }
148
            f.createNewFile();
149
        } catch (IOException e) {
150
            // TODO Auto-generated catch block
151
        }
152
        FileOutputStream fOut = null;
153
        try {
154
            fOut = new FileOutputStream(f);
155
        } catch (Exception e) {
156
            e.printStackTrace();
157
        }
158
        mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
159
//        Log.e("!!!", "下载图片");
160
        Toast.makeText(AboutActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
161
        try {
162
            fOut.flush();
163
        } catch (IOException e) {
164
            e.printStackTrace();
165
        }
166
        try {
167
            fOut.close();
168
        } catch (IOException e) {
169
            e.printStackTrace();
170
        }
171
        MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");
172
        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
173
        Uri uri = Uri.fromFile(new File(dir_path));
174
        intent.setData(uri);
175
        mContext.sendBroadcast(intent);
176
    }
138

177 139

178 140
    @Override
179 141
    public void onPermissionsGranted(int requestCode, List<String> perms) {

+ 6 - 5
app/src/main/java/com/electric/chargingpile/activity/AdinShowActivity.java

@ -14,7 +14,6 @@ import android.net.Uri;
14 14
import android.net.http.SslError;
15 15
import android.os.Build;
16 16
import android.os.Bundle;
17
import android.os.Environment;
18 17
import android.provider.MediaStore;
19 18
import androidx.annotation.NonNull;
20 19
import androidx.core.content.FileProvider;
@ -63,6 +62,8 @@ import okhttp3.Call;
63 62
import pub.devrel.easypermissions.AfterPermissionGranted;
64 63
import pub.devrel.easypermissions.EasyPermissions;
65 64
65
import static com.electric.chargingpile.util.PhotoUtils.CACHE_DIR;
66
66 67
public class AdinShowActivity extends Activity implements View.OnClickListener {
67 68
    private WebView webView;
68 69
    private ImageView iv_back, iv_close;
@ -978,9 +979,9 @@ public class AdinShowActivity extends Activity implements View.OnClickListener {
978 979
    // 拍照
979 980
    private void takeCamera() {
980 981
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
981
        if (ImageUitl.hasSdcard()) {
982
//        if (ImageUitl.hasSdcard()) {
982 983
            String fileName = "android" + System.currentTimeMillis() / 1000 + ".jpg";
983
            cameraFilePath = ImageUitl.getPath(Environment.getExternalStorageDirectory() + "/" + "cdz") + "/" + fileName;
984
            cameraFilePath = ImageUitl.getPath( CACHE_DIR) + "/" + fileName;
984 985
            File imageFile = ImageUitl.getFile(cameraFilePath);
985 986
            Uri uri = parseUri(imageFile);
986 987
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
@ -990,7 +991,7 @@ public class AdinShowActivity extends Activity implements View.OnClickListener {
990 991
                e.printStackTrace();
991 992
            }
992 993
993
        }
994
//        }
994 995
    }
995 996
996 997
    private Uri parseUri(File cameraFile) {
@ -1028,7 +1029,7 @@ public class AdinShowActivity extends Activity implements View.OnClickListener {
1028 1029
                result = data.getData();
1029 1030
            }
1030 1031
            if (result == null && ImageUitl.hasFile(cameraFilePath)) {
1031
                result = Uri.fromFile(new File(cameraFilePath));
1032
                result = parseUri(new File(cameraFilePath));
1032 1033
            }
1033 1034
1034 1035
            if (mOpenFileWebChromeClient.mFilePathCallbacks != null) {

+ 45 - 180
app/src/main/java/com/electric/chargingpile/activity/AlterOneActivity.java

@ -5,23 +5,18 @@ import android.annotation.SuppressLint;
5 5
import android.app.Activity;
6 6
import android.app.ProgressDialog;
7 7
import android.app.TimePickerDialog;
8
import android.content.ContentValues;
9 8
import android.content.Context;
10 9
import android.content.Intent;
11
import android.database.Cursor;
12 10
import android.graphics.Bitmap;
13 11
import android.graphics.BitmapFactory;
14 12
import android.graphics.Color;
15 13
import android.graphics.Matrix;
16
import android.graphics.drawable.BitmapDrawable;
17 14
import android.graphics.drawable.ColorDrawable;
18 15
import android.net.Uri;
19 16
import android.os.Build;
20 17
import android.os.Bundle;
21
import android.os.Environment;
22 18
import android.os.Handler;
23 19
import android.os.Message;
24
import android.provider.MediaStore;
25 20
import android.util.Base64;
26 21
import android.util.DisplayMetrics;
27 22
import android.util.Log;
@ -48,28 +43,29 @@ import androidx.annotation.NonNull;
48 43
import com.electric.chargingpile.R;
49 44
import com.electric.chargingpile.application.MainApplication;
50 45
import com.electric.chargingpile.data.Zhan;
46
import com.electric.chargingpile.engine.GlideEngine;
51 47
import com.electric.chargingpile.util.BarColorUtil;
52 48
import com.electric.chargingpile.util.Bimp;
53 49
import com.electric.chargingpile.util.DES3;
54
import com.electric.chargingpile.util.FileUtils;
55 50
import com.electric.chargingpile.util.ImageItem;
56
import com.electric.chargingpile.util.ImageUtils;
57 51
import com.electric.chargingpile.util.PublicWay;
58 52
import com.electric.chargingpile.util.Res;
59 53
import com.electric.chargingpile.util.StatusConstants;
60 54
import com.electric.chargingpile.util.ToastUtil;
61 55
import com.electric.chargingpile.util.UploadUtil;
56
import com.electric.chargingpile.util.Util;
62 57
import com.electric.chargingpile.view.AlertDialogTwo;
63 58
import com.electric.chargingpile.view.CustomProgressDialog;
64 59
import com.google.android.gms.appindexing.Action;
65 60
import com.google.android.gms.appindexing.AppIndex;
66 61
import com.google.android.gms.appindexing.Thing;
67 62
import com.google.android.gms.common.api.GoogleApiClient;
63
import com.luck.picture.lib.PictureSelector;
64
import com.luck.picture.lib.animators.AnimationType;
65
import com.luck.picture.lib.config.PictureConfig;
66
import com.luck.picture.lib.config.PictureMimeType;
67
import com.luck.picture.lib.entity.LocalMedia;
68 68
import com.umeng.analytics.MobclickAgent;
69
import com.zhihu.matisse.Matisse;
70
import com.zhihu.matisse.MimeType;
71
import com.zhihu.matisse.engine.impl.GlideEngine;
72
import com.zhihu.matisse.internal.entity.CaptureStrategy;
73 69

74 70
import org.json.JSONException;
75 71
import org.json.JSONObject;
@ -129,16 +125,13 @@ public class AlterOneActivity extends Activity implements View.OnClickListener,
129 125
    private EditText et_remark;
130 126
    private GridAdapter adapter;
131 127
    private View parentView;
132
    private PopupWindow pop = null;
128

133 129
    Bitmap bm = null;
134
    private String camePath;//拍照路径
135
    private LinearLayout ll_popup;
130

136 131
    private Animation animation;
137 132
    private ImageView point;
138 133
    private Toast toast = null;
139
    private static final String PHOTO_FILE_NAME = "android.jpg";
140
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
141
    private File tempFile;
134

142 135
    private static final int PHOTO_REQUEST_CAMERA = 1;
143 136
    private static final int PHOTO_REQUEST_GALLERY = 2;
144 137
    private static final int PHOTO_REQUEST_CUT = 3;
@ -189,11 +182,10 @@ public class AlterOneActivity extends Activity implements View.OnClickListener,
189 182
     * See https://g.co/AppIndexing/AndroidStudio for more information.
190 183
     */
191 184
    private GoogleApiClient client;
192

185
    private List<LocalMedia> mSelectionData =new ArrayList<LocalMedia>();
193 186
    @Override
194 187
    protected void onCreate(Bundle savedInstanceState) {
195 188
        super.onCreate(savedInstanceState);
196
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
197 189
        Res.init(this);
198 190
        bimap = BitmapFactory.decodeResource(
199 191
                getResources(),
@ -223,64 +215,6 @@ public class AlterOneActivity extends Activity implements View.OnClickListener,
223 215
    }
224 216

225 217
    public void Init() {
226

227
        pop = new PopupWindow(AlterOneActivity.this);
228

229
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
230

231
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
232

233
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
234
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
235
        pop.setBackgroundDrawable(new BitmapDrawable());
236
        pop.setFocusable(true);
237
        pop.setOutsideTouchable(true);
238
        pop.setContentView(view);
239

240

241
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
242
        Button bt1 = (Button) view.findViewById(R.id.item_popupwindows_camera);
243
        Button bt2 = (Button) view.findViewById(R.id.item_popupwindows_Photo);
244
        Button bt3 = (Button) view.findViewById(R.id.item_popupwindows_cancel);
245
        parent.setOnClickListener(new View.OnClickListener() {
246

247
            @Override
248
            public void onClick(View v) {
249
                pop.dismiss();
250
                ll_popup.clearAnimation();
251
            }
252
        });
253
        bt1.setOnClickListener(new View.OnClickListener() {
254
            @Override
255
            public void onClick(View v) {
256
                pop.dismiss();
257
                ll_popup.clearAnimation();
258
                if (MainScanActivity.isCameraUseable()) {
259
                    photo();
260
                } else {
261
                    ToastUtil.showToast(getApplicationContext(), "您当前关闭了调用摄像头权限", Toast.LENGTH_SHORT);
262
                }
263
            }
264
        });
265
        bt2.setOnClickListener(new View.OnClickListener() {
266
            @Override
267
            public void onClick(View v) {
268
                Intent intent = new Intent(AlterOneActivity.this,
269
                        AlbumActivityAlter.class);
270
                startActivity(intent);
271
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
272
                pop.dismiss();
273
                ll_popup.clearAnimation();
274
            }
275
        });
276
        bt3.setOnClickListener(new View.OnClickListener() {
277
            @Override
278
            public void onClick(View v) {
279
                pop.dismiss();
280
                ll_popup.clearAnimation();
281
            }
282
        });
283

284 218
        noScrollgridview = (GridView) findViewById(R.id.noScrollgridview);
285 219
        noScrollgridview.setSelector(new ColorDrawable(Color.TRANSPARENT));
286 220
        adapter = new GridAdapter(this);
@ -306,15 +240,26 @@ public class AlterOneActivity extends Activity implements View.OnClickListener,
306 240
     * 调用图库选择
307 241
     */
308 242
    private void callGallery() {
309
        Matisse.from(AlterOneActivity.this)
310
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
311
                .showSingleMediaType(true)
312
                .countable(true)
313
                .maxSelectable(PIC_NUM - Bimp.tempSelectBitmap.size())
314
                .capture(true)
315
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
316
                .imageEngine(new GlideEngine())
317
                .forResult(REQUEST_CODE_CHOOSE);
243
        PictureSelector.create(this)
244
                    .openGallery(PictureMimeType.ofImage())
245
                    .maxSelectNum(PIC_NUM-Bimp.tempSelectBitmap.size())
246
                    .selectionMode(PictureConfig.MULTIPLE)
247
                   // .selectionData(mSelectionData)//是否传入已选图片
248
                    .isCompress(true)//是否压缩
249
                    .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
250
                    .isGif(true)//是否显示gif
251
                    .isAndroidQTransform(true)
252
                    .imageEngine(GlideEngine.createGlideEngine())
253
                    .isWeChatStyle(false)// 是否开启微信图片选择风格
254
                    .isUseCustomCamera(false)// 是否使用自定义相机
255
                    .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
256
                    .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
257
                    .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
258
                    .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
259
                    .imageSpanCount(4)// 每行显示个数
260
                    .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
261
                    .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
262
                    .forResult(REQUEST_CODE_CHOOSE);
318 263
    }
319 264

320 265
    @Override
@ -344,16 +289,22 @@ public class AlterOneActivity extends Activity implements View.OnClickListener,
344 289
                    @Override
345 290
                    public ObservableSource<Boolean> apply(Intent intent) throws Exception {
346 291
                        try {
292
                            mSelectionData= PictureSelector.obtainMultipleResult(data);
347 293

348
                            List<Uri> uriList = Matisse.obtainResult(data);
349
                            for (Uri uri : uriList) {
350
                                Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
351
                                File file = FileUtils.from(AlterOneActivity.this, uri);
352

353
                                bitmap = FileUtils.rotateIfRequired(file, bitmap);
354
                                bitmap = imageZoom(bitmap);
294
                            for (LocalMedia localMedia : mSelectionData) {
295
//                                Bitmap bitmap = BitmapFactory.decodeFile(getContentResolver().openInputStream(uri));
296
//                                File file = FileUtils.from(AlterOneActivity.this, uri);
297
//
298
//                                bitmap = FileUtils.rotateIfRequired(file, bitmap);
299
//                                bitmap = imageZoom(bitmap);
300
                                String path="";
301
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
302
                                    path= localMedia.getAndroidQToPath();
303
                                }else{
304
                                    path=localMedia.getPath();
305
                                }
355 306
                                ImageItem takePhoto = new ImageItem();
356
                                takePhoto.setBitmap(bitmap);
307
                                takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
357 308
                                Bimp.tempSelectBitmap.add(takePhoto);
358 309
                            }
359 310
                            return Observable.just(true);
@ -613,18 +564,6 @@ public class AlterOneActivity extends Activity implements View.OnClickListener,
613 564

614 565
    private static final int TAKE_PICTURE = 0x000001;
615 566

616

617
    public void photo() {
618

619
        if (hasSdcard()) {
620
            int currentapiVersion = Build.VERSION.SDK_INT;
621
            Log.e("currentapiVersion", "currentapiVersion====>" + currentapiVersion);
622
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//���������
623
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
624
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
625
        }
626
    }
627

628 567
    @Override
629 568
    public void onClick(View v) {
630 569
        if (imm.isActive()) {
@ -841,81 +780,7 @@ public class AlterOneActivity extends Activity implements View.OnClickListener,
841 780
        }
842 781
    }
843 782

844
    private void crop(Uri uri, Uri cutImgUri) {
845
        Intent intent = new Intent("com.android.camera.action.CROP");
846
        intent.setDataAndType(getImageContentUri(this, tempFile), "image/*");
847
        intent.putExtra("crop", "true");
848
        intent.putExtra("outputFormat", "JPEG");
849
        intent.putExtra("noFaceDetection", true);
850
        intent.putExtra("return-data", false);
851
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
852
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
853
    }
854

855
    private boolean hasSdcard() {
856
        if (Environment.getExternalStorageState().equals(
857
                Environment.MEDIA_MOUNTED)) {
858
            return true;
859
        } else {
860
            return false;
861
        }
862
    }
863

864
    private static String getPath(String path) {
865
        File f = new File(path);
866
        if (!f.exists()) {
867
            f.mkdirs();
868
        }
869
        return f.getAbsolutePath();
870
    }
871

872
    private File getFile(String path) {
873
        File f = new File(path);
874
        if (!f.exists()) {
875
            try {
876
                f.createNewFile();
877
            } catch (IOException e) {
878
                e.printStackTrace();
879
            }
880
        }
881
        return f;
882
    }
883

884
    public Bitmap decodeUriAsBitmap(Uri uri) {
885
        Bitmap bitmap = null;
886
        try {
887
            bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri));
888
        } catch (FileNotFoundException e) {
889
            e.printStackTrace();
890
            return null;
891
        }
892
        return bitmap;
893
    }
894

895
    public static Uri getImageContentUri(Context context, File imageFile) {
896
        String filePath = imageFile.getAbsolutePath();
897
        Cursor cursor = context.getContentResolver().query(
898
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
899
                new String[]{MediaStore.Images.Media._ID},
900
                MediaStore.Images.Media.DATA + "=? ",
901
                new String[]{filePath}, null);
902 783

903
        if (cursor != null && cursor.moveToFirst()) {
904
            int id = cursor.getInt(cursor
905
                    .getColumnIndex(MediaStore.MediaColumns._ID));
906
            Uri baseUri = Uri.parse("content://media/external/images/media");
907
            return Uri.withAppendedPath(baseUri, "" + id);
908
        } else {
909
            if (imageFile.exists()) {
910
                ContentValues values = new ContentValues();
911
                values.put(MediaStore.Images.Media.DATA, filePath);
912
                return context.getContentResolver().insert(
913
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
914
            } else {
915
                return null;
916
            }
917
        }
918
    }
919 784

920 785
    public static boolean containsEmoji(String source) {
921 786
        int len = source.length();

+ 47 - 21
app/src/main/java/com/electric/chargingpile/activity/CarOwnerCertificateActivity.java

@ -13,6 +13,7 @@ import android.graphics.BitmapFactory;
13 13
import android.graphics.Matrix;
14 14
import android.graphics.drawable.Drawable;
15 15
import android.net.Uri;
16
import android.os.Build;
16 17
import android.os.Bundle;
17 18
import android.text.TextUtils;
18 19
import android.util.Base64;
@ -32,6 +33,7 @@ import com.bumptech.glide.request.transition.Transition;
32 33
import com.electric.chargingpile.R;
33 34
import com.electric.chargingpile.application.MainApplication;
34 35
import com.electric.chargingpile.data.CarOwnerCertificateBean;
36
import com.electric.chargingpile.engine.GlideEngine;
35 37
import com.electric.chargingpile.entity.CarBrandGroupEntity;
36 38
import com.electric.chargingpile.entity.CarModelEntity;
37 39
import com.electric.chargingpile.entity.CarSeriesEntity;
@ -44,13 +46,16 @@ import com.electric.chargingpile.util.FileUtils;
44 46
import com.electric.chargingpile.util.JsonUtils;
45 47
import com.electric.chargingpile.util.LoadingDialog;
46 48
import com.electric.chargingpile.util.ToastUtil;
49
import com.electric.chargingpile.util.Util;
47 50
import com.electric.chargingpile.view.TextImageView;
48 51
import com.google.gson.Gson;
49 52
import com.google.gson.reflect.TypeToken;
50
import com.zhihu.matisse.Matisse;
51
import com.zhihu.matisse.MimeType;
52
import com.zhihu.matisse.engine.impl.GlideEngine;
53
import com.zhihu.matisse.internal.entity.CaptureStrategy;
53
54
import com.luck.picture.lib.PictureSelector;
55
import com.luck.picture.lib.animators.AnimationType;
56
import com.luck.picture.lib.config.PictureConfig;
57
import com.luck.picture.lib.config.PictureMimeType;
58
import com.luck.picture.lib.entity.LocalMedia;
54 59
import com.zhy.http.okhttp.OkHttpUtils;
55 60
import com.zhy.http.okhttp.callback.StringCallback;
56 61
@ -417,15 +422,23 @@ public class CarOwnerCertificateActivity extends AppCompatActivity implements Vi
417 422
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
418 423
419 424
                try {
420
                    List<Uri> uriList = Matisse.obtainResult(data);
421
                    Uri uri = uriList.get(0);
422
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
423
                    File file = FileUtils.from(CarOwnerCertificateActivity.this, uri);
424
425
                    bitmap = FileUtils.rotateIfRequired(file, bitmap);
426
                    bitmap = imageZoom(bitmap);
427
                    insertBitmap = bitmap;
428
                    subscriber.onComplete();
425
//                    List<Uri> uriList = Matisse.obtainResult(data);
426
                    List<LocalMedia> localList = PictureSelector.obtainMultipleResult(data);
427
                    if (localList !=null && localList.size()>0 ){
428
                        LocalMedia localMedia = localList.get(0);
429
//                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
430
//                        File file = FileUtils.from(CarOwnerCertificateActivity.this, uri);
431
//                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
432
                        String path="";
433
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
434
                            path= localMedia.getAndroidQToPath();
435
                        }else{
436
                            path=localMedia.getPath();
437
                        }
438
                        insertBitmap =imageZoom( BitmapFactory.decodeFile(path));
439
                        subscriber.onComplete();
440
                    }
441
429 442
                } catch (Exception e) {
430 443
                    e.printStackTrace();
431 444
                    subscriber.onError(e);
@ -638,15 +651,28 @@ public class CarOwnerCertificateActivity extends AppCompatActivity implements Vi
638 651
    @AfterPermissionGranted(RC_ALBUM_PERM)
639 652
    public void permissionTask() {
640 653
        if (isPermissionOK()) {
641
            Matisse.from(CarOwnerCertificateActivity.this)
642
                    .choose(MimeType.of(MimeType.JPEG, MimeType.PNG))
643
                    .showSingleMediaType(true)
644
                    .countable(true)
645
                    .maxSelectable(1)
646
                    .capture(true)
647
                    .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
648
                    .imageEngine(new GlideEngine())
654
            PictureSelector.create(this)
655
                    .openGallery(PictureMimeType.ofImage())
656
                    .maxSelectNum(1)
657
                    .selectionMode(PictureConfig.SINGLE)
658
                    .isSingleDirectReturn(true)
659
                    .isCompress(true)//是否压缩
660
                    .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
661
                    .isGif(false)//是否显示gif
662
                    .isAndroidQTransform(true)
663
                    .imageEngine(GlideEngine.createGlideEngine())
664
                    .isWeChatStyle(false)// 是否开启微信图片选择风格
665
                    .isUseCustomCamera(false)// 是否使用自定义相机
666
                    .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
667
                    .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
668
                    .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
669
                    .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
670
                    .imageSpanCount(4)// 每行显示个数
671
                    .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
672
                    .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
649 673
                    .forResult(REQUEST_CODE_CHOOSE);
674
675
650 676
        } else {
651 677
            EasyPermissions.requestPermissions(
652 678
                    this, "充电桩想要获取您的图片读取权限,是否允许?",

+ 50 - 160
app/src/main/java/com/electric/chargingpile/activity/ChargingCommentActivity.java

@ -3,23 +3,18 @@ package com.electric.chargingpile.activity;
3 3
import android.Manifest;
4 4
import android.app.Activity;
5 5
import android.app.ProgressDialog;
6
import android.content.ContentValues;
7 6
import android.content.Context;
8 7
import android.content.Intent;
9
import android.database.Cursor;
10 8
import android.graphics.Bitmap;
11 9
import android.graphics.BitmapFactory;
12 10
import android.graphics.Color;
13 11
import android.graphics.Matrix;
14 12
import android.graphics.drawable.BitmapDrawable;
15 13
import android.graphics.drawable.ColorDrawable;
16
import android.net.Uri;
17 14
import android.os.Build;
18 15
import android.os.Bundle;
19
import android.os.Environment;
20 16
import android.os.Handler;
21 17
import android.os.Message;
22
import android.provider.MediaStore;
23 18
import android.text.Editable;
24 19
import android.text.TextWatcher;
25 20
import android.util.Base64;
@ -32,10 +27,8 @@ import android.view.animation.AnimationUtils;
32 27
import android.view.inputmethod.InputMethodManager;
33 28
import android.widget.AdapterView;
34 29
import android.widget.BaseAdapter;
35
import android.widget.Button;
36 30
import android.widget.GridView;
37 31
import android.widget.ImageView;
38
import android.widget.LinearLayout;
39 32
import android.widget.PopupWindow;
40 33
import android.widget.RelativeLayout;
41 34
import android.widget.ScrollView;
@ -50,12 +43,11 @@ import com.electric.chargingpile.application.MainApplication;
50 43
import com.electric.chargingpile.data.ChargingShareBean;
51 44
import com.electric.chargingpile.data.CommentsBean;
52 45
import com.electric.chargingpile.data.RObject;
46
import com.electric.chargingpile.engine.GlideEngine;
53 47
import com.electric.chargingpile.util.BarColorUtil;
54 48
import com.electric.chargingpile.util.Bimp;
55 49
import com.electric.chargingpile.util.DES3;
56
import com.electric.chargingpile.util.FileUtils;
57 50
import com.electric.chargingpile.util.ImageItem;
58
import com.electric.chargingpile.util.ImageUtils;
59 51
import com.electric.chargingpile.util.JsonUtils;
60 52
import com.electric.chargingpile.util.LoadingDialog;
61 53
import com.electric.chargingpile.util.Md5Util;
@ -64,15 +56,17 @@ import com.electric.chargingpile.util.Res;
64 56
import com.electric.chargingpile.util.StatusConstants;
65 57
import com.electric.chargingpile.util.ToastUtil;
66 58
import com.electric.chargingpile.util.UploadUtil;
59
import com.electric.chargingpile.util.Util;
67 60
import com.electric.chargingpile.view.HongBaoDialog;
68 61
import com.electric.chargingpile.view.HongBaoResultDialog;
69 62
import com.electric.chargingpile.view.REditText;
70 63
import com.electric.chargingpile.view.RatingBarView;
64
import com.luck.picture.lib.PictureSelector;
65
import com.luck.picture.lib.animators.AnimationType;
66
import com.luck.picture.lib.config.PictureConfig;
67
import com.luck.picture.lib.config.PictureMimeType;
68
import com.luck.picture.lib.entity.LocalMedia;
71 69
import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet;
72
import com.zhihu.matisse.Matisse;
73
import com.zhihu.matisse.MimeType;
74
import com.zhihu.matisse.engine.impl.GlideEngine;
75
import com.zhihu.matisse.internal.entity.CaptureStrategy;
76 70
import com.zhy.http.okhttp.OkHttpUtils;
77 71
import com.zhy.http.okhttp.callback.StringCallback;
78 72
import com.zhy.view.flowlayout.FlowLayout;
@ -84,7 +78,6 @@ import org.json.JSONObject;
84 78
85 79
import java.io.ByteArrayOutputStream;
86 80
import java.io.File;
87
import java.io.FileNotFoundException;
88 81
import java.io.IOException;
89 82
import java.net.URLEncoder;
90 83
import java.util.ArrayList;
@ -137,12 +130,9 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
137 130
    private String select_s = "";
138 131
    private String select_ss = "";
139 132
    private TextView tv_grade;
140
    private File tempFile;
141
    private static String PHOTO_FILE_NAME = "";
142
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
133
143 134
    public static Bitmap bimap;
144
    private PopupWindow pop = null;
145
    private LinearLayout ll_popup;
135
146 136
    private GridView noScrollgridview;
147 137
    private ScrollView sv;
148 138
    private GridAdapter adapter;
@ -193,7 +183,7 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
193 183
            super.handleMessage(msg);
194 184
        }
195 185
    };
196
186
    private List<LocalMedia> mSelectionData =new ArrayList<LocalMedia>();
197 187
    @Override
198 188
    protected void onCreate(Bundle savedInstanceState) {
199 189
        super.onCreate(savedInstanceState);
@ -201,9 +191,6 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
201 191
        BarColorUtil.initStatusBarColor(ChargingCommentActivity.this);
202 192
        dialog = new LoadingDialog(this);
203 193
        dialog.setCanceledOnTouchOutside(false);
204
        long appTime1 = System.currentTimeMillis() / 1000;
205
        PHOTO_FILE_NAME = "android" + appTime1 + ".jpg";
206
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
207 194
        Res.init(this);
208 195
        bimap = BitmapFactory.decodeResource(
209 196
                getResources(),
@ -451,61 +438,6 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
451 438
    }
452 439
453 440
    public void Init() {
454
        pop = new PopupWindow(ChargingCommentActivity.this);
455
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
456
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
457
458
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
459
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
460
        pop.setBackgroundDrawable(new BitmapDrawable());
461
        pop.setFocusable(true);
462
        pop.setOutsideTouchable(true);
463
        pop.setContentView(view);
464
465
466
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
467
        Button bt1 = (Button) view
468
                .findViewById(R.id.item_popupwindows_camera);
469
        Button bt2 = (Button) view
470
                .findViewById(R.id.item_popupwindows_Photo);
471
        Button bt3 = (Button) view
472
                .findViewById(R.id.item_popupwindows_cancel);
473
        parent.setOnClickListener(new View.OnClickListener() {
474
475
            @Override
476
            public void onClick(View v) {
477
                // TODO Auto-generated method stub
478
                pop.dismiss();
479
                ll_popup.clearAnimation();
480
            }
481
        });
482
        bt1.setOnClickListener(new View.OnClickListener() {
483
            public void onClick(View v) {
484
                photo();
485
//                saveFullImage();
486
                pop.dismiss();
487
//                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
488
//                ((Activity) mContext).startActivityForResult(intent, 2);
489
                ll_popup.clearAnimation();
490
            }
491
        });
492
        bt2.setOnClickListener(new View.OnClickListener() {
493
            public void onClick(View v) {
494
                Intent intent = new Intent(ChargingCommentActivity.this,
495
                        AlbumActivityCharging.class);
496
                startActivity(intent);
497
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
498
//                startActivityForResult(intent, 1);
499
                pop.dismiss();
500
                ll_popup.clearAnimation();
501
            }
502
        });
503
        bt3.setOnClickListener(new View.OnClickListener() {
504
            public void onClick(View v) {
505
                pop.dismiss();
506
                ll_popup.clearAnimation();
507
            }
508
        });
509 441
510 442
        noScrollgridview = (GridView) findViewById(R.id.noScrollgridview);
511 443
        noScrollgridview.setSelector(new ColorDrawable(Color.TRANSPARENT));
@ -534,6 +466,7 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
534 466
     * 调用图库选择
535 467
     */
536 468
    private void callGallery() {
469
/*
537 470
        Matisse.from(ChargingCommentActivity.this)
538 471
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
539 472
                .showSingleMediaType(true)
@ -543,6 +476,29 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
543 476
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
544 477
                .imageEngine(new GlideEngine())
545 478
                .forResult(REQUEST_CODE_CHOOSE);
479
*/
480
481
        PictureSelector.create(this)
482
                .openGallery(PictureMimeType.ofImage())
483
                .maxSelectNum(PIC_NUM)
484
                .selectionMode(PictureConfig.MULTIPLE)
485
                .selectionData(mSelectionData)//是否传入已选图片
486
                .isCompress(true)//是否压缩
487
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
488
                .isGif(true)//是否显示gif
489
                .isAndroidQTransform(true)
490
                .imageEngine(GlideEngine.createGlideEngine())
491
                .isWeChatStyle(false)// 是否开启微信图片选择风格
492
                .isUseCustomCamera(false)// 是否使用自定义相机
493
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
494
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
495
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
496
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
497
                .imageSpanCount(4)// 每行显示个数
498
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
499
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
500
                .forResult(REQUEST_CODE_CHOOSE);
501
546 502
    }
547 503
548 504
    @Override
@ -571,15 +527,23 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
571 527
            @Override
572 528
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
573 529
                try {
574
                    List<Uri> uriList = Matisse.obtainResult(data);
575
                    for (Uri uri : uriList) {
576
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
577
                        File file = FileUtils.from(ChargingCommentActivity.this, uri);
578
579
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
580
                        bitmap = imageZoom(bitmap);
530
                    mSelectionData= PictureSelector.obtainMultipleResult(data);
531
532
//                    List<Uri> uriList = Matisse.obtainResult(data);
533
                    for (LocalMedia media : mSelectionData) {
534
//                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
535
//                        File file = FileUtils.from(ChargingCommentActivity.this, uri);
536
//
537
//                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
538
//                        bitmap = imageZoom(bitmap);
539
                        String path="";
540
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
541
                            path= media.getAndroidQToPath();
542
                        }else{
543
                            path=media.getPath();
544
                        }
581 545
                        ImageItem takePhoto = new ImageItem();
582
                        takePhoto.setBitmap(bitmap);
546
                        takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
583 547
                        Bimp.tempSelectBitmap.add(takePhoto);
584 548
                        subscriber.onNext("");
585 549
                    }
@ -1173,81 +1137,7 @@ public class ChargingCommentActivity extends Activity implements View.OnClickLis
1173 1137
        }
1174 1138
    }
1175 1139
1176
    public void photo() {
1177
        if (hasSdcard()) {
1178
            int currentapiVersion = Build.VERSION.SDK_INT;
1179
            Log.e("currentapiVersion", "currentapiVersion====>" + currentapiVersion);
1180
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//���������
1181
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
1182
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
1183
        }
1184
    }
1185 1140
1186
    private boolean hasSdcard() {
1187
        if (Environment.getExternalStorageState().equals(
1188
                Environment.MEDIA_MOUNTED)) {
1189
            return true;
1190
        } else {
1191
            return false;
1192
        }
1193
    }
1194
1195
    private void crop(Uri uri, Uri cutImgUri) {
1196
        // �ü�ͼƬ��ͼ
1197
        Intent intent = new Intent("com.android.camera.action.CROP");
1198
        intent.setDataAndType(getImageContentUri(this, tempFile), "image/*");
1199
1200
        intent.putExtra("crop", "true");
1201
        // �ü���ı�����1��1
1202
//        intent.putExtra("aspectX", 16);
1203
//        intent.putExtra("aspectY", 9);
1204
//        // �ü������ͼƬ�ijߴ��С
1205
//        intent.putExtra("outputX", 640);
1206
//        intent.putExtra("outputY", 360);
1207
1208
        // ͼƬ��ʽ
1209
        intent.putExtra("outputFormat", "JPEG");
1210
        intent.putExtra("noFaceDetection", true);// ȡ������ʶ��
1211
        intent.putExtra("return-data", false);// true:������uri��false������uri
1212
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));//д���ȡ��ͼƬ
1213
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
1214
    }
1215
1216
    public static Uri getImageContentUri(Context context, File imageFile) {
1217
        String filePath = imageFile.getAbsolutePath();
1218
        Cursor cursor = context.getContentResolver().query(
1219
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
1220
                new String[]{MediaStore.Images.Media._ID},
1221
                MediaStore.Images.Media.DATA + "=? ",
1222
                new String[]{filePath}, null);
1223
1224
        if (cursor != null && cursor.moveToFirst()) {
1225
            int id = cursor.getInt(cursor
1226
                    .getColumnIndex(MediaStore.MediaColumns._ID));
1227
            Uri baseUri = Uri.parse("content://media/external/images/media");
1228
            return Uri.withAppendedPath(baseUri, "" + id);
1229
        } else {
1230
            if (imageFile.exists()) {
1231
                ContentValues values = new ContentValues();
1232
                values.put(MediaStore.Images.Media.DATA, filePath);
1233
                return context.getContentResolver().insert(
1234
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
1235
            } else {
1236
                return null;
1237
            }
1238
        }
1239
    }
1240
1241
    public Bitmap decodeUriAsBitmap(Uri uri) {
1242
        Bitmap bitmap = null;
1243
        try {
1244
            bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri));
1245
        } catch (FileNotFoundException e) {
1246
            e.printStackTrace();
1247
            return null;
1248
        }
1249
        return bitmap;
1250
    }
1251 1141
1252 1142
    protected void onRestart() {
1253 1143
        adapter.update();

+ 3 - 67
app/src/main/java/com/electric/chargingpile/activity/ClaimDataActivity.java

@ -8,7 +8,7 @@ import android.content.SharedPreferences;
8 8
import android.graphics.Bitmap;
9 9
import android.net.Uri;
10 10
import android.os.Bundle;
11
import android.os.Environment;
11
12 12
import android.os.Handler;
13 13
import android.os.Message;
14 14
import android.telephony.TelephonyManager;
@ -50,6 +50,8 @@ import java.util.Date;
50 50
import java.util.HashMap;
51 51
import java.util.Map;
52 52
53
import static com.electric.chargingpile.util.PhotoUtils.CACHE_DIR;
54
53 55
54 56
public class ClaimDataActivity extends Activity {
55 57
    private TextView zhanName, address, shuoming;
@ -582,31 +584,6 @@ public class ClaimDataActivity extends Activity {
582 584
    }
583 585
584 586
    /**
585
     * 裁剪图片方法实现 @param uri
586
     */
587
    public void startPhotoZoom(Uri uri) {
588
        /*
589
         *   * 至于下面这个Intent的ACTION是怎么知道的,大家可以看下自己路径下的如下网页   *
590
         * yourself_sdk_path/docs/reference/android/content/Intent.html   *
591
         * 直接在里面Ctrl+F搜:CROP ,之前小马没仔细看过,其实安卓系统早已经有自带图片裁剪功能,   * 是直接调本地库的,不懂C C++
592
         * 这个不做详细了解去了,有轮子就用轮子,不再研究轮子是怎么   * 制做的了...吼吼
593
         */
594
        Intent intent = new Intent("com.android.camera.action.CROP");
595
        intent.setDataAndType(uri, "image/*");
596
597
        // 下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪
598
        intent.putExtra("crop", "true");
599
        // aspectX aspectY 是宽高的比例
600
        intent.putExtra("aspectX", 4);
601
        intent.putExtra("aspectY", 3);
602
        // outputX outputY 是裁剪图片宽高
603
        intent.putExtra("outputX", 400);
604
        intent.putExtra("outputY", 300);
605
        intent.putExtra("return-data", true);
606
        startActivityForResult(intent, 3);
607
    }
608
609
    /**
610 587
     * 保存裁剪之后的图片数据
611 588
     **/
612 589
    private void setPicToView(Intent picdata) {
@ -623,33 +600,6 @@ public class ClaimDataActivity extends Activity {
623 600
        }
624 601
    }
625 602
626
    private String bitmapToBase64(Bitmap bitmap) {
627
628
        String result = null;
629
        ByteArrayOutputStream baos = null;
630
        try {
631
            if (bitmap != null) {
632
                baos = new ByteArrayOutputStream();
633
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
634
                baos.flush();
635
                baos.close();
636
                byte[] bitmapBytes = baos.toByteArray();
637
                result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
638
            }
639
        } catch (IOException e) {
640
            e.printStackTrace();
641
        } finally {
642
            try {
643
                if (baos != null) {
644
                    baos.flush();
645
                    baos.close();
646
                }
647
            } catch (IOException e) {
648
                e.printStackTrace();
649
            }
650
        }
651
        return result;
652
    }
653 603
654 604
    @Override
655 605
    public void onActivityResult(final int requestCode, int resultCode,
@ -660,20 +610,6 @@ public class ClaimDataActivity extends Activity {
660 610
            return;
661 611
662 612
        switch (requestCode) {
663
            // 如果是直接从相册获取
664
            case 1:
665
                if (data != null) {
666
                    startPhotoZoom(data.getData());
667
                    Toast.makeText(mContext, "拖动正方形角可调整剪切大小",
668
                            android.widget.Toast.LENGTH_SHORT).show();
669
                }
670
                break;
671
            // 如果是调用相机拍照时
672
            case 2:
673
                File temp = new File(Environment.getExternalStorageDirectory()
674
                        + "/androidapp.jpg");
675
                startPhotoZoom(Uri.fromFile(temp));
676
                break;
677 613
            // 取得裁剪后的图片
678 614
            case 3:
679 615
                if (data != null) {

+ 96 - 78
app/src/main/java/com/electric/chargingpile/activity/ClaimSurveyTwoActivity.java

@ -16,7 +16,6 @@ import android.graphics.drawable.ColorDrawable;
16 16
import android.net.Uri;
17 17
import android.os.Build;
18 18
import android.os.Bundle;
19
import android.os.Environment;
20 19
import android.os.Handler;
21 20
import android.os.Message;
22 21
import android.provider.MediaStore;
@ -71,11 +70,13 @@ import com.amap.api.services.geocoder.RegeocodeResult;
71 70
import com.electric.chargingpile.R;
72 71
import com.electric.chargingpile.application.MainApplication;
73 72
import com.electric.chargingpile.data.Zhan;
73
import com.electric.chargingpile.engine.GlideEngine;
74 74
import com.electric.chargingpile.util.Bimp;
75 75
import com.electric.chargingpile.util.DES3;
76 76
import com.electric.chargingpile.util.FileUtils;
77 77
import com.electric.chargingpile.util.ImageItem;
78 78
import com.electric.chargingpile.util.OkHttpUtil;
79
import com.electric.chargingpile.util.PhotoUtils;
79 80
import com.electric.chargingpile.util.PublicWay;
80 81
import com.electric.chargingpile.util.Res;
81 82
import com.electric.chargingpile.util.SharedPreferencesUtil;
@ -88,9 +89,15 @@ import com.google.android.gms.appindexing.Action;
88 89
import com.google.android.gms.appindexing.AppIndex;
89 90
import com.google.android.gms.appindexing.Thing;
90 91
import com.google.android.gms.common.api.GoogleApiClient;
92
import com.luck.picture.lib.PictureSelector;
93
import com.luck.picture.lib.animators.AnimationType;
94
import com.luck.picture.lib.config.PictureConfig;
95
import com.luck.picture.lib.config.PictureMimeType;
96
import com.luck.picture.lib.entity.LocalMedia;
91 97
import com.squareup.okhttp.Request;
92 98
import com.squareup.okhttp.Response;
93 99
import com.umeng.analytics.MobclickAgent;
100
import com.yalantis.ucrop.view.OverlayView;
94 101
95 102
import org.json.JSONException;
96 103
import org.json.JSONObject;
@ -122,11 +129,11 @@ public class ClaimSurveyTwoActivity extends Activity implements View.OnClickList
122 129
    private String camePath;//拍照路径
123 130
    //    private LocationMode mCurrentMode;
124 131
    private static final String PHOTO_FILE_NAME = "android.jpg";
125
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
132
    private static final String PHOTO_FILE_PATH = getPath(PhotoUtils.CACHE_DIR);
126 133
    private File tempFile;
127 134
    private static final int PHOTO_REQUEST_CAMERA = 1;
128 135
    private static final int PHOTO_REQUEST_GALLERY = 2;
129
    private static final int PHOTO_REQUEST_CUT = 3;
136
130 137
    private String gd_jing, gd_wei;
131 138
    String ls_jing, ls_wei;
132 139
    private boolean isTouch = false;
@ -369,11 +376,12 @@ public class ClaimSurveyTwoActivity extends Activity implements View.OnClickList
369 376
        });
370 377
        bt2.setOnClickListener(new View.OnClickListener() {
371 378
            public void onClick(View v) {
372
                Intent intent = new Intent(ClaimSurveyTwoActivity.this,
373
                        AlbumActivity4claim.class);
374
                startActivity(intent);
375
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
379
//                Intent intent = new Intent(ClaimSurveyTwoActivity.this,
380
//                        AlbumActivity4claim.class);
381
//                startActivity(intent);
382
//                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
376 383
//                startActivityForResult(intent, 1);
384
                openPhotoAlbum();
377 385
                pop.dismiss();
378 386
                ll_popup.clearAnimation();
379 387
            }
@ -1817,34 +1825,69 @@ public class ClaimSurveyTwoActivity extends Activity implements View.OnClickList
1817 1825
1818 1826
    private static final int TAKE_PICTURE = 0x000001;
1819 1827
1820
//    public void photo() {
1821
//        Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1822
//        startActivityForResult(openCameraIntent, TAKE_PICTURE);
1823
////        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1824
////        File file = new File(Environment.getExternalStorageDirectory() + "/myimage/", String.valueOf(System
1825
////                .currentTimeMillis()) + ".jpg");
1826
////        camePath = file.getPath();
1827
////        Uri imageUri = Uri.fromFile(file);
1828
////        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
1829
////        startActivityForResult(intent, TAKE_PICTURE);
1830
//    }
1828
1831 1829
1832 1830
    public void photo() {
1833
//		Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1834
//		startActivityForResult(openCameraIntent, TAKE_PICTURE);
1835
//        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1836
//        File file = new File(Environment.getExternalStorageDirectory() + "/myimage/", String.valueOf(System
1837
//                .currentTimeMillis()) + ".jpg");
1838
//        camePath = file.getPath();
1839
//        Uri imageUri = Uri.fromFile(file);
1840
//        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
1841
//        startActivityForResult(intent, TAKE_PICTURE);
1842
        if (hasSdcard()) {
1843
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//���������
1844
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
1845
//            intent.putExtra(MediaStore.EXTRA_OUTPUT, cutImgUri);
1846
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
1847
        }
1831
        PictureSelector.create(this)
1832
                .openCamera(PictureMimeType.ofImage())
1833
                .selectionMode(PictureConfig.SINGLE)
1834
                .isSingleDirectReturn(true)
1835
                .isCompress(true)//是否压缩
1836
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
1837
                .isGif(false)//是否显示gif
1838
                .isAndroidQTransform(true)
1839
                .imageEngine(GlideEngine.createGlideEngine())
1840
                .isWeChatStyle(false)// 是否开启微信图片选择风格
1841
                .isUseCustomCamera(false)// 是否使用自定义相机
1842
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
1843
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
1844
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
1845
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
1846
                .imageSpanCount(4)// 每行显示个数
1847
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
1848
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
1849
                .isEnableCrop(true)
1850
                .rotateEnabled(false)//裁剪是否可旋转图片
1851
                .freeStyleCropMode(OverlayView.DEFAULT_FREESTYLE_CROP_MODE)// 裁剪框拖动模式
1852
                .isCropDragSmoothToCenter(true)// 裁剪框拖动时图片自动跟随居中
1853
                .circleDimmedLayer(false)// 是否开启圆形裁剪
1854
                .isDragFrame(true)//是否可拖动裁剪框(固定)
1855
                .showCropFrame(true)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
1856
                .showCropGrid(true)//是否显示裁剪矩形网格 圆形裁剪时建议设为false
1857
                .forResult(PHOTO_REQUEST_CAMERA);
1858
1859
    }
1860
    private void openPhotoAlbum() {
1861
        PictureSelector.create(this)
1862
                .openGallery(PictureMimeType.ofImage())
1863
                .isCamera(false)//列表是否显示拍照按钮
1864
                .selectionMode(PictureConfig.SINGLE)
1865
                .isSingleDirectReturn(true)//PictureConfig.SINGLE模式下是否直接返回
1866
                .isCompress(true)//是否压缩
1867
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
1868
                .isGif(false)//是否显示gif
1869
                .isAndroidQTransform(true)
1870
                .imageEngine(GlideEngine.createGlideEngine())
1871
                .isWeChatStyle(false)// 是否开启微信图片选择风格
1872
                .isUseCustomCamera(false)// 是否使用自定义相机
1873
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
1874
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
1875
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
1876
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
1877
                .imageSpanCount(4)// 每行显示个数
1878
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
1879
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
1880
                .rotateEnabled(false)//裁剪是否可旋转图片
1881
                .isEnableCrop(true)
1882
                .rotateEnabled(false)//裁剪是否可旋转图片
1883
                .setCircleStrokeWidth(8)//设置圆形裁剪边框粗细
1884
                .freeStyleCropMode(OverlayView.DEFAULT_FREESTYLE_CROP_MODE)// 裁剪框拖动模式
1885
                .isCropDragSmoothToCenter(true)// 裁剪框拖动时图片自动跟随居中
1886
                .circleDimmedLayer(true)// 是否开启圆形裁剪
1887
                .isDragFrame(true)//是否可拖动裁剪框(固定)
1888
                .showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
1889
                .showCropGrid(false)//是否显示裁剪矩形网格 圆形裁剪时建议设为false
1890
                .forResult(PHOTO_REQUEST_GALLERY);
1848 1891
    }
1849 1892
1850 1893
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
@ -1861,23 +1904,27 @@ public class ClaimSurveyTwoActivity extends Activity implements View.OnClickList
1861 1904
        }
1862 1905
        System.out.println("--------data------->" + data);
1863 1906
        //���ѡȡ
1864
        if (requestCode == PHOTO_REQUEST_CAMERA && resultCode == Activity.RESULT_OK) {
1865
            //��������ͼƬ�ͽ�ȡ���ͼƬ�ļ���д����ͬһ���ļ���photo.jpg
1866
            crop(Uri.fromFile(tempFile), Uri.fromFile(tempFile));
1867
        }
1868
        //���ؽ�ȡ��ͼƬ
1869
        else if (requestCode == PHOTO_REQUEST_CUT && data != null) {
1870
            //���д�ͼʹ��Uri
1871
            Bitmap bitmap = decodeUriAsBitmap(Uri.fromFile(tempFile));//decode bitmap
1872
//            mFace.setImageBitmap(bitmap);
1873
            String fileName = String.valueOf(System.currentTimeMillis());
1874
            ImageItem takePhoto = new ImageItem();
1875
            takePhoto.setBitmap(bitmap);
1876
            takePhoto.setImagePath(FileUtils.SDPATH + fileName + ".JPEG");
1877
            Bimp.tempSelectBitmap.add(takePhoto);
1878
        } else {
1879
//            Toast.makeText(getApplicationContext(), "��ȡͼƬʧ��", Toast.LENGTH_SHORT).show();
1907
        if (resultCode == Activity.RESULT_OK){
1908
            if (requestCode == PHOTO_REQUEST_CAMERA || requestCode == PHOTO_REQUEST_GALLERY) {
1909
                List<LocalMedia> medias = PictureSelector.obtainMultipleResult(data);
1910
                if (medias != null && medias.size() > 0) {
1911
                    String path = "";
1912
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
1913
                        path = medias.get(0).getAndroidQToPath();
1914
                    } else {
1915
                        path = medias.get(0).getPath();
1916
                    }
1917
                    Bitmap bitmap = BitmapFactory.decodeFile(path);
1918
                    ImageItem takePhoto = new ImageItem();
1919
                    takePhoto.setBitmap(bitmap);
1920
                    takePhoto.setImagePath(path);
1921
                    Bimp.tempSelectBitmap.add(takePhoto);
1922
                }
1923
1924
            }
1925
1880 1926
        }
1927
1881 1928
        super.onActivityResult(requestCode, resultCode, data);
1882 1929
    }
1883 1930
@ -2026,35 +2073,6 @@ public class ClaimSurveyTwoActivity extends Activity implements View.OnClickList
2026 2073
//        bdLocation.recycle();
2027 2074
    }
2028 2075
2029
    private void crop(Uri uri, Uri cutImgUri) {
2030
        // �ü�ͼƬ��ͼ
2031
        Intent intent = new Intent("com.android.camera.action.CROP");
2032
        intent.setDataAndType(uri, "image/*");
2033
        intent.putExtra("crop", "true");
2034
        // �ü���ı�����1��1
2035
//        intent.putExtra("aspectX", 4);
2036
//        intent.putExtra("aspectY", 3);
2037
        // �ü������ͼƬ�ijߴ��С
2038
//        intent.putExtra("outputX", 400);
2039
//        intent.putExtra("outputY", 300);
2040
2041
        // ͼƬ��ʽ
2042
        intent.putExtra("outputFormat", "JPEG");
2043
        intent.putExtra("noFaceDetection", true);// ȡ������ʶ��
2044
        intent.putExtra("return-data", false);// true:������uri��false������uri
2045
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cutImgUri);//д���ȡ��ͼƬ
2046
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
2047
    }
2048
2049
    private boolean hasSdcard() {
2050
        if (Environment.getExternalStorageState().equals(
2051
                Environment.MEDIA_MOUNTED)) {
2052
            return true;
2053
        } else {
2054
            return false;
2055
        }
2056
    }
2057
2058 2076
    private static String getPath(String path) {
2059 2077
        File f = new File(path);
2060 2078
        if (!f.exists()) {

+ 7 - 26
app/src/main/java/com/electric/chargingpile/activity/CompletePhotoActivity.java

@ -1,31 +1,12 @@
1 1
package com.electric.chargingpile.activity;
2 2

3 3
import android.app.Activity;
4
import android.app.AlertDialog;
5
import android.content.ContentResolver;
6
import android.content.DialogInterface;
7
import android.content.Intent;
8
import android.database.Cursor;
9
import android.graphics.Bitmap;
10
import android.graphics.BitmapFactory;
11
import android.net.Uri;
12
import android.os.Bundle;
13
import android.os.Environment;
14
import android.provider.MediaStore;
15
import android.text.TextUtils;
16
import android.util.Log;
17
import android.view.View;
18
import android.widget.ImageView;
19
import android.widget.LinearLayout;
20

21
import com.electric.chargingpile.R;
22
import com.electric.chargingpile.util.ImageTools;
23

24
import java.io.File;
25

26

27
public class CompletePhotoActivity extends Activity implements View.OnClickListener {
28
    LinearLayout ll_addMore_photo;
4
/**
5
 * 已废弃
6
 * */
7
@Deprecated
8
public class CompletePhotoActivity extends Activity {
9
 /*   LinearLayout ll_addMore_photo;
29 10
    private static String srcPath = "";
30 11
    private ImageView image, updatePhoto_moveback;
31 12
    private File mPhotoFile;
@ -169,5 +150,5 @@ public class CompletePhotoActivity extends Activity implements View.OnClickListe
169 150
                image.setImageBitmap(BitmapFactory.decodeFile(srcPath));
170 151
            }
171 152
        }
172
    }
153
    }*/
173 154
}

+ 58 - 23
app/src/main/java/com/electric/chargingpile/activity/EditAnswerActivity.java

@ -7,12 +7,9 @@ import android.content.Intent;
7 7
import android.graphics.Bitmap;
8 8
import android.graphics.BitmapFactory;
9 9
import android.graphics.Matrix;
10
import android.net.Uri;
10
import android.os.Build;
11 11
import android.os.Bundle;
12 12
import android.os.Handler;
13
14
import androidx.appcompat.app.AppCompatActivity;
15
16 13
import android.util.DisplayMetrics;
17 14
import android.util.Log;
18 15
import android.util.TypedValue;
@ -27,31 +24,31 @@ import android.widget.RelativeLayout;
27 24
import android.widget.TextView;
28 25
import android.widget.Toast;
29 26
27
import androidx.appcompat.app.AppCompatActivity;
28
30 29
import com.electric.chargingpile.R;
31 30
import com.electric.chargingpile.application.MainApplication;
31
import com.electric.chargingpile.engine.GlideEngine;
32 32
import com.electric.chargingpile.util.AndroidBug5497Workaround;
33 33
import com.electric.chargingpile.util.BarColorUtil;
34 34
import com.electric.chargingpile.util.FileUtils;
35
import com.electric.chargingpile.util.ImageItem;
36 35
import com.electric.chargingpile.util.ImageUitl;
37
import com.electric.chargingpile.util.ImageUtils;
38 36
import com.electric.chargingpile.util.JsonUtils;
39
import com.electric.chargingpile.util.ScreenUtils;
40 37
import com.electric.chargingpile.util.StringUtils;
41 38
import com.electric.chargingpile.util.ToastUtil;
42
import com.electric.chargingpile.view.CarTypeDialog;
39
import com.electric.chargingpile.util.Util;
43 40
import com.electric.chargingpile.view.xrichtext.RichTextEditorForA;
44 41
import com.electric.chargingpile.view.xrichtext.SDCardUtil;
45
import com.zhihu.matisse.Matisse;
46
import com.zhihu.matisse.MimeType;
47
import com.zhihu.matisse.engine.impl.GlideEngine;
48
import com.zhihu.matisse.internal.entity.CaptureStrategy;
42
import com.luck.picture.lib.PictureSelector;
43
import com.luck.picture.lib.animators.AnimationType;
44
import com.luck.picture.lib.config.PictureConfig;
45
import com.luck.picture.lib.config.PictureMimeType;
46
import com.luck.picture.lib.entity.LocalMedia;
49 47
import com.zhy.http.okhttp.OkHttpUtils;
50 48
import com.zhy.http.okhttp.callback.StringCallback;
51 49
52 50
import java.io.ByteArrayOutputStream;
53 51
import java.io.File;
54
import java.util.ArrayList;
55 52
import java.util.HashMap;
56 53
import java.util.Iterator;
57 54
import java.util.List;
@ -333,19 +330,33 @@ public class EditAnswerActivity extends AppCompatActivity implements View.OnClic
333 330
334 331
                try {
335 332
                    et_new_content.measure(0, 0);
336
                    List<Uri> uriList = Matisse.obtainResult(data);
337
                    Uri uri = uriList.get(0);
338
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
339
                    File file = FileUtils.from(EditAnswerActivity.this, uri);
333
//                    List<Uri> uriList = Matisse.obtainResult(data);
334
                   List<LocalMedia> selectionData= PictureSelector.obtainMultipleResult(data);
335
                    if (selectionData!=null && selectionData.size()>0){
336
                        LocalMedia media = selectionData.get(0);
337
338
//                        Uri uri = uriList.get(0);
339
//                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
340
//                        File file = FileUtils.from(EditAnswerActivity.this, uri);
341
//
342
//                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
343
//                        bitmap = imageZoom(bitmap);
344
                        String path="";
345
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
346
                            path= media.getAndroidQToPath();
347
                        }else{
348
                            path=media.getPath();
349
                        }
350
                        insertBitmap = imageZoom(BitmapFactory.decodeFile(path));
340 351
341
                    bitmap = FileUtils.rotateIfRequired(file, bitmap);
342
                    bitmap = imageZoom(bitmap);
343
                    insertBitmap = bitmap;
352
                        u_path = path;
344 353
345
                    u_path = SDCardUtil.saveToSdCard(bitmap);
354
                        subscriber.onNext(u_path);
355
                        subscriber.onComplete();
356
                    }else{
357
                        subscriber.onError(new Exception());
358
                    }
346 359
347
                    subscriber.onNext(u_path);
348
                    subscriber.onComplete();
349 360
                } catch (Exception e) {
350 361
                    e.printStackTrace();
351 362
                    subscriber.onError(e);
@ -502,6 +513,7 @@ public class EditAnswerActivity extends AppCompatActivity implements View.OnClic
502 513
     * 调用图库选择
503 514
     */
504 515
    private void callGallery() {
516
/*
505 517
        Matisse.from(EditAnswerActivity.this)
506 518
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
507 519
                .showSingleMediaType(true)
@ -511,6 +523,29 @@ public class EditAnswerActivity extends AppCompatActivity implements View.OnClic
511 523
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
512 524
                .imageEngine(new GlideEngine())
513 525
                .forResult(REQUEST_CODE_CHOOSE);
526
*/
527
528
        PictureSelector.create(this)
529
                .openGallery(PictureMimeType.ofImage())
530
                .maxSelectNum(1)
531
                .selectionMode(PictureConfig.SINGLE)
532
                .isSingleDirectReturn(true)
533
                .isCompress(true)//是否压缩
534
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
535
                .isGif(true)//是否显示gif
536
                .isAndroidQTransform(true)
537
                .imageEngine(GlideEngine.createGlideEngine())
538
                .isWeChatStyle(false)// 是否开启微信图片选择风格
539
                .isUseCustomCamera(false)// 是否使用自定义相机
540
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
541
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
542
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
543
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
544
                .imageSpanCount(4)// 每行显示个数
545
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
546
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
547
                .forResult(REQUEST_CODE_CHOOSE);
548
514 549
    }
515 550
516 551
    @Override

+ 63 - 22
app/src/main/java/com/electric/chargingpile/activity/EditQuestionTwoActivity.java

@ -8,6 +8,7 @@ import android.graphics.Bitmap;
8 8
import android.graphics.BitmapFactory;
9 9
import android.graphics.Matrix;
10 10
import android.net.Uri;
11
import android.os.Build;
11 12
import android.os.Bundle;
12 13
import android.os.Handler;
13 14
@ -27,6 +28,7 @@ import android.widget.Toast;
27 28
28 29
import com.electric.chargingpile.R;
29 30
import com.electric.chargingpile.application.MainApplication;
31
import com.electric.chargingpile.engine.GlideEngine;
30 32
import com.electric.chargingpile.util.AndroidBug5497Workaround;
31 33
import com.electric.chargingpile.util.BarColorUtil;
32 34
import com.electric.chargingpile.util.FileUtils;
@ -35,14 +37,17 @@ import com.electric.chargingpile.util.JsonUtils;
35 37
import com.electric.chargingpile.util.ScreenUtils;
36 38
import com.electric.chargingpile.util.StringUtils;
37 39
import com.electric.chargingpile.util.ToastUtil;
40
import com.electric.chargingpile.util.Util;
38 41
import com.electric.chargingpile.view.CarTypeDialog;
39 42
import com.electric.chargingpile.view.xrichtext.RichTextEditor;
40 43
import com.electric.chargingpile.view.xrichtext.SDCardUtil;
44
import com.luck.picture.lib.PictureSelector;
45
import com.luck.picture.lib.animators.AnimationType;
46
import com.luck.picture.lib.config.PictureConfig;
47
import com.luck.picture.lib.config.PictureMimeType;
48
import com.luck.picture.lib.entity.LocalMedia;
41 49
import com.umeng.analytics.MobclickAgent;
42
import com.zhihu.matisse.Matisse;
43
import com.zhihu.matisse.MimeType;
44
import com.zhihu.matisse.engine.impl.GlideEngine;
45
import com.zhihu.matisse.internal.entity.CaptureStrategy;
50
46 51
import com.zhy.http.okhttp.OkHttpUtils;
47 52
import com.zhy.http.okhttp.callback.StringCallback;
48 53
@ -353,19 +358,33 @@ public class EditQuestionTwoActivity extends AppCompatActivity implements View.O
353 358
354 359
                try {
355 360
                    et_new_content.measure(0, 0);
356
                    List<Uri> uriList = Matisse.obtainResult(data);
357
                    Uri uri = uriList.get(0);
358
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
359
                    File file = FileUtils.from(EditQuestionTwoActivity.this, uri);
361
                    List<LocalMedia> selectionData= PictureSelector.obtainMultipleResult(data);
362
                    if (selectionData!=null && selectionData.size()>0) {
363
                        LocalMedia media = selectionData.get(0);
364
                        /*List<Uri> uriList = Matisse.obtainResult(data);
365
                        Uri uri = uriList.get(0);
366
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
367
                        File file = FileUtils.from(EditQuestionTwoActivity.this, uri);
368
369
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
370
                        bitmap = imageZoom(bitmap);
371
                        insertBitmap = bitmap;*/
372
                        String path="";
373
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
374
                            path= media.getAndroidQToPath();
375
                        }else{
376
                            path=media.getPath();
377
                        }
378
                        insertBitmap = imageZoom(BitmapFactory.decodeFile(path));
360 379
361
                    bitmap = FileUtils.rotateIfRequired(file, bitmap);
362
                    bitmap = imageZoom(bitmap);
363
                    insertBitmap = bitmap;
380
                        u_path = path;
364 381
365
                    u_path = SDCardUtil.saveToSdCard(bitmap);
382
                        subscriber.onNext(u_path);
383
                        subscriber.onComplete();
384
                    }else{
385
                        subscriber.onError(new Exception());
386
                    }
366 387
367
                    subscriber.onNext(u_path);
368
                    subscriber.onComplete();
369 388
                } catch (Exception e) {
370 389
                    e.printStackTrace();
371 390
                    subscriber.onError(e);
@ -531,15 +550,37 @@ public class EditQuestionTwoActivity extends AppCompatActivity implements View.O
531 550
     * 调用图库选择
532 551
     */
533 552
    private void callGallery() {
534
        Matisse.from(EditQuestionTwoActivity.this)
535
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
536
                .showSingleMediaType(true)
537
                .countable(true)
538
                .maxSelectable(1)
539
                .capture(true)
540
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
541
                .imageEngine(new GlideEngine())
553
//        Matisse.from(EditQuestionTwoActivity.this)
554
//                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
555
//                .showSingleMediaType(true)
556
//                .countable(true)
557
//                .maxSelectable(1)
558
//                .capture(true)
559
//                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
560
//                .imageEngine(new GlideEngine())
561
//                .forResult(REQUEST_CODE_CHOOSE);
562
563
        PictureSelector.create(this)
564
                .openGallery(PictureMimeType.ofImage())
565
                .maxSelectNum(1)
566
                .selectionMode(PictureConfig.SINGLE)
567
                .isSingleDirectReturn(true)
568
                .isCompress(true)//是否压缩
569
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
570
                .isGif(true)//是否显示gif
571
                .isAndroidQTransform(true)
572
                .imageEngine(GlideEngine.createGlideEngine())
573
                .isWeChatStyle(false)// 是否开启微信图片选择风格
574
                .isUseCustomCamera(false)// 是否使用自定义相机
575
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
576
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
577
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
578
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
579
                .imageSpanCount(4)// 每行显示个数
580
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
581
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
542 582
                .forResult(REQUEST_CODE_CHOOSE);
583
543 584
    }
544 585
545 586
    @Override

+ 53 - 168
app/src/main/java/com/electric/chargingpile/activity/FeedbackActivity.java

@ -16,10 +16,11 @@ import android.graphics.drawable.ColorDrawable;
16 16
import android.net.Uri;
17 17
import android.os.Build;
18 18
import android.os.Bundle;
19
import android.os.Environment;
19

20

20 21
import android.os.Handler;
21 22
import android.os.Message;
22
import android.provider.MediaStore;
23

23 24
import android.text.Editable;
24 25
import android.text.TextWatcher;
25 26
import android.util.Base64;
@ -45,6 +46,7 @@ import android.widget.Toast;
45 46
import com.electric.chargingpile.R;
46 47
import com.electric.chargingpile.application.MainApplication;
47 48
import com.electric.chargingpile.data.UploadPic;
49
import com.electric.chargingpile.engine.GlideEngine;
48 50
import com.electric.chargingpile.util.BarColorUtil;
49 51
import com.electric.chargingpile.util.Bimp;
50 52
import com.electric.chargingpile.util.FileUtils;
@ -56,11 +58,13 @@ import com.electric.chargingpile.util.Res;
56 58
import com.electric.chargingpile.util.ToastUtil;
57 59
import com.electric.chargingpile.util.UploadUtil;
58 60
import com.electric.chargingpile.util.Util;
61
import com.luck.picture.lib.PictureSelector;
62
import com.luck.picture.lib.animators.AnimationType;
63
import com.luck.picture.lib.config.PictureConfig;
64
import com.luck.picture.lib.config.PictureMimeType;
65
import com.luck.picture.lib.entity.LocalMedia;
59 66
import com.umeng.analytics.MobclickAgent;
60
import com.zhihu.matisse.Matisse;
61
import com.zhihu.matisse.MimeType;
62
import com.zhihu.matisse.engine.impl.GlideEngine;
63
import com.zhihu.matisse.internal.entity.CaptureStrategy;
67

64 68
import com.zhy.http.okhttp.OkHttpUtils;
65 69
import com.zhy.http.okhttp.callback.StringCallback;
66 70

@ -89,12 +93,11 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
89 93
    private static final int PIC_NUM = 3;
90 94
    private ImageView ivBack;
91 95
    private TextView tv_right;
92
    private static String PHOTO_FILE_NAME = "";
93
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
96

97

94 98
    private GridView noScrollgridview;
95
    private PopupWindow pop = null;
96
    private LinearLayout ll_popup;
97
    private File tempFile;
99

100

98 101
    Bitmap bm = null;
99 102
    private static final int PHOTO_REQUEST_CAMERA = 1;
100 103
    private static final int PHOTO_REQUEST_GALLERY = 2;
@ -134,7 +137,7 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
134 137
        }
135 138
    };
136 139

137

140
    private List<LocalMedia> mSelectionData =new ArrayList<LocalMedia>();
138 141
    @Override
139 142
    protected void onCreate(Bundle savedInstanceState) {
140 143
        super.onCreate(savedInstanceState);
@ -143,9 +146,6 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
143 146
        initView();
144 147
        Res.init(this);
145 148
        PublicWay.activityList.add(this);
146
        long appTime1 = System.currentTimeMillis() / 1000;
147
        PHOTO_FILE_NAME = "android" + appTime1 + ".jpg";
148
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
149 149
        dialog = new LoadingDialog(this);
150 150
        dialog.setCanceledOnTouchOutside(false);
151 151
        Init();
@ -271,95 +271,7 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
271 271
        return f;
272 272
    }
273 273

274
    private static String getPath(String path) {
275
        File f = new File(path);
276
        if (!f.exists()) {
277
            f.mkdirs();
278
        }
279
        return f.getAbsolutePath();
280
    }
281

282
    private boolean hasSdcard() {
283
        if (Environment.getExternalStorageState().equals(
284
                Environment.MEDIA_MOUNTED)) {
285
            return true;
286
        } else {
287
            return false;
288
        }
289
    }
290

291 274
    public void Init() {
292
        pop = new PopupWindow(FeedbackActivity.this);
293
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
294
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
295

296
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
297
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
298
        pop.setBackgroundDrawable(new BitmapDrawable());
299
        pop.setFocusable(true);
300
        pop.setOutsideTouchable(true);
301
        pop.setContentView(view);
302

303

304
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
305
        Button bt1 = (Button) view
306
                .findViewById(R.id.item_popupwindows_camera);
307
        Button bt2 = (Button) view
308
                .findViewById(R.id.item_popupwindows_Photo);
309
        Button bt3 = (Button) view
310
                .findViewById(R.id.item_popupwindows_cancel);
311
        parent.setOnClickListener(new View.OnClickListener() {
312

313
            @Override
314
            public void onClick(View v) {
315
                // TODO Auto-generated method stub
316
                pop.dismiss();
317
                ll_popup.clearAnimation();
318
            }
319
        });
320
        bt1.setOnClickListener(new View.OnClickListener() {
321
            public void onClick(View v) {
322
                pop.dismiss();
323
                ll_popup.clearAnimation();
324
                if (MainScanActivity.isCameraUseable()) {
325
                    photo();
326
                } else {
327
                    ToastUtil.showToast(getApplicationContext(), "您当前关闭了调用摄像头权限", Toast.LENGTH_SHORT);
328
//					new AlertDialogTwo(FeedbackActivity.this).builder()
329
//							.setMsg("您当前关闭了调用摄像头权限,是否去打开?")
330
//							.setPositiveButton("去打开", new View.OnClickListener() {
331
//								@Override
332
//								public void onClick(View v) {
333
//									Intent intent = new Intent(Settings.ACTION_SETTINGS);
334
//									startActivity(intent);
335
//								}
336
//							}).setNegativeButton("忽略", new View.OnClickListener() {
337
//						@Override
338
//						public void onClick(View v) {
339
//
340
//						}
341
//					}).show();
342
                }
343
            }
344
        });
345
        bt2.setOnClickListener(new View.OnClickListener() {
346
            public void onClick(View v) {
347
                Intent intent = new Intent(FeedbackActivity.this,
348
                        AlbumActivityFeedback.class);
349
                startActivity(intent);
350
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
351
//                startActivityForResult(intent, 1);
352
                pop.dismiss();
353
                ll_popup.clearAnimation();
354
            }
355
        });
356
        bt3.setOnClickListener(new View.OnClickListener() {
357
            public void onClick(View v) {
358
                pop.dismiss();
359
                ll_popup.clearAnimation();
360
            }
361
        });
362

363 275
        noScrollgridview = (GridView) findViewById(R.id.noScrollgridview);
364 276
        noScrollgridview.setSelector(new ColorDrawable(Color.TRANSPARENT));
365 277
        adapter = new GridAdapter(this);
@ -387,6 +299,7 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
387 299
     * 调用图库选择
388 300
     */
389 301
    private void callGallery() {
302
/*
390 303
        Matisse.from(FeedbackActivity.this)
391 304
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
392 305
                .showSingleMediaType(true)
@ -396,6 +309,28 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
396 309
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
397 310
                .imageEngine(new GlideEngine())
398 311
                .forResult(REQUEST_CODE_CHOOSE);
312
*/
313

314
        PictureSelector.create(this)
315
                .openGallery(PictureMimeType.ofImage())
316
                .maxSelectNum(PIC_NUM)
317
                .selectionMode(PictureConfig.MULTIPLE)
318
                .selectionData(mSelectionData)//是否传入已选图片
319
                .isCompress(true)//是否压缩
320
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
321
                .isGif(true)//是否显示gif
322
                .isAndroidQTransform(true)
323
                .imageEngine(GlideEngine.createGlideEngine())
324
                .isWeChatStyle(false)// 是否开启微信图片选择风格
325
                .isUseCustomCamera(false)// 是否使用自定义相机
326
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
327
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
328
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
329
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
330
                .imageSpanCount(4)// 每行显示个数
331
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
332
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
333
                .forResult(REQUEST_CODE_CHOOSE);
399 334

400 335

401 336
    }
@ -427,15 +362,22 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
427 362
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
428 363

429 364
                try {
430
                    List<Uri> uriList = Matisse.obtainResult(data);
431
                    for (Uri uri: uriList) {
432
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
433
                        File file = FileUtils.from(FeedbackActivity.this, uri);
434

435
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
436
                        bitmap = imageZoom(bitmap);
365
//                    List<Uri> uriList = Matisse.obtainResult(data);
366
                    mSelectionData = PictureSelector.obtainMultipleResult(data);
367
                    for (LocalMedia media: mSelectionData) {
368
//                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
369
//                        File file = FileUtils.from(FeedbackActivity.this, uri);
370
//
371
//                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
372
//                        bitmap = imageZoom(bitmap);
373
                        String path="";
374
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
375
                            path= media.getAndroidQToPath();
376
                        }else{
377
                            path=media.getPath();
378
                        }
437 379
                        ImageItem takePhoto = new ImageItem();
438
                        takePhoto.setBitmap(bitmap);
380
                        takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
439 381
                        Bimp.tempSelectBitmap.add(takePhoto);
440 382
                        subscriber.onNext("");
441 383
                    }
@ -582,63 +524,6 @@ public class FeedbackActivity extends Activity implements OnClickListener, EasyP
582 524
        }
583 525
    }
584 526

585
    public void photo() {
586
        if (hasSdcard()) {
587
            int currentapiVersion = Build.VERSION.SDK_INT;
588
            Log.e("currentapiVersion", "currentapiVersion====>" + currentapiVersion);
589
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//���������
590
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
591
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
592
        }
593
    }
594

595
    public static Uri getImageContentUri(Context context, File imageFile) {
596
        String filePath = imageFile.getAbsolutePath();
597
        Cursor cursor = context.getContentResolver().query(
598
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
599
                new String[]{MediaStore.Images.Media._ID},
600
                MediaStore.Images.Media.DATA + "=? ",
601
                new String[]{filePath}, null);
602

603
        if (cursor != null && cursor.moveToFirst()) {
604
            int id = cursor.getInt(cursor
605
                    .getColumnIndex(MediaStore.MediaColumns._ID));
606
            Uri baseUri = Uri.parse("content://media/external/images/media");
607
            return Uri.withAppendedPath(baseUri, "" + id);
608
        } else {
609
            if (imageFile.exists()) {
610
                ContentValues values = new ContentValues();
611
                values.put(MediaStore.Images.Media.DATA, filePath);
612
                return context.getContentResolver().insert(
613
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
614
            } else {
615
                return null;
616
            }
617
        }
618
    }
619

620
    private void crop(Uri uri, Uri cutImgUri) {
621
        Intent intent = new Intent("com.android.camera.action.CROP");
622
        intent.setDataAndType(getImageContentUri(this, tempFile), "image/*");
623

624
        intent.putExtra("crop", "true");
625
        intent.putExtra("outputFormat", "JPEG");
626
        intent.putExtra("noFaceDetection", true);
627
        intent.putExtra("return-data", false);
628
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
629
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
630
    }
631

632
    public Bitmap decodeUriAsBitmap(Uri uri) {
633
        Bitmap bitmap = null;
634
        try {
635
            bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri));
636
        } catch (FileNotFoundException e) {
637
            e.printStackTrace();
638
            return null;
639
        }
640
        return bitmap;
641
    }
642 527

643 528

644 529
    protected void onRestart() {

+ 5 - 10
app/src/main/java/com/electric/chargingpile/activity/FindActivity.java

@ -12,20 +12,14 @@ import android.content.IntentFilter;
12 12
import android.content.SharedPreferences;
13 13
import android.content.res.AssetManager;
14 14
import android.graphics.Bitmap;
15
import android.graphics.BitmapFactory;
16 15
import android.net.ConnectivityManager;
17 16
import android.net.NetworkInfo;
18 17
import android.net.Uri;
19 18
import android.os.Build;
20 19
import android.os.Bundle;
21
import android.os.Environment;
22 20
import android.os.Handler;
23 21
import android.os.Message;
24 22
import android.provider.Settings;
25
import androidx.annotation.NonNull;
26
import androidx.appcompat.app.AppCompatActivity;
27
import androidx.recyclerview.widget.GridLayoutManager;
28
import androidx.recyclerview.widget.RecyclerView;
29 23
import android.util.Log;
30 24
import android.view.KeyEvent;
31 25
import android.view.LayoutInflater;
@ -37,6 +31,11 @@ import android.widget.RelativeLayout;
37 31
import android.widget.TextView;
38 32
import android.widget.Toast;
39 33
34
import androidx.annotation.NonNull;
35
import androidx.appcompat.app.AppCompatActivity;
36
import androidx.recyclerview.widget.GridLayoutManager;
37
import androidx.recyclerview.widget.RecyclerView;
38
40 39
import com.blankj.utilcode.util.EmptyUtils;
41 40
import com.blankj.utilcode.util.LogUtils;
42 41
import com.electric.chargingpile.R;
@ -49,7 +48,6 @@ import com.electric.chargingpile.data.FindData;
49 48
import com.electric.chargingpile.manager.ProfileManager;
50 49
import com.electric.chargingpile.util.BarColorUtil;
51 50
import com.electric.chargingpile.util.DES3;
52
import com.electric.chargingpile.util.ImageTools;
53 51
import com.electric.chargingpile.util.JsonUtils;
54 52
import com.electric.chargingpile.util.OkHttpUtil;
55 53
import com.electric.chargingpile.util.ToastUtil;
@ -68,7 +66,6 @@ import org.json.JSONArray;
68 66
import org.zackratos.ultimatebar.UltimateBar;
69 67
70 68
import java.io.BufferedReader;
71
import java.io.File;
72 69
import java.io.IOException;
73 70
import java.io.InputStreamReader;
74 71
import java.net.URLEncoder;
@ -87,8 +84,6 @@ import okhttp3.Call;
87 84
import pub.devrel.easypermissions.AfterPermissionGranted;
88 85
import pub.devrel.easypermissions.AppSettingsDialog;
89 86
import pub.devrel.easypermissions.EasyPermissions;
90
import top.zibin.luban.Luban;
91
import top.zibin.luban.OnCompressListener;
92 87
93 88
public class FindActivity extends AppCompatActivity implements View.OnClickListener, EasyPermissions.PermissionCallbacks {
94 89
    private static final String TAG = "FindActivity";

+ 21 - 18
app/src/main/java/com/electric/chargingpile/activity/H5Activity.java

@ -16,10 +16,11 @@ import android.net.Uri;
16 16
import android.net.http.SslError;
17 17
import android.os.Build;
18 18
import android.os.Bundle;
19
import android.os.Environment;
20 19
import android.provider.MediaStore;
20
21 21
import androidx.annotation.NonNull;
22 22
import androidx.core.content.FileProvider;
23
23 24
import android.util.Log;
24 25
import android.view.KeyEvent;
25 26
import android.view.View;
@ -46,6 +47,7 @@ import com.electric.chargingpile.manager.ProfileManager;
46 47
import com.electric.chargingpile.util.DES3;
47 48
import com.electric.chargingpile.util.ImageUitl;
48 49
import com.electric.chargingpile.util.JsonUtils;
50
import com.electric.chargingpile.util.PhotoUtils;
49 51
import com.electric.chargingpile.util.ToastUtil;
50 52
import com.google.gson.Gson;
51 53
import com.umeng.analytics.MobclickAgent;
@ -70,7 +72,7 @@ import okhttp3.Call;
70 72
import pub.devrel.easypermissions.AfterPermissionGranted;
71 73
import pub.devrel.easypermissions.EasyPermissions;
72 74
73
public class H5Activity extends Activity implements View.OnClickListener, PlatformActionListener,EasyPermissions.PermissionCallbacks {
75
public class H5Activity extends Activity implements View.OnClickListener, PlatformActionListener, EasyPermissions.PermissionCallbacks {
74 76
    private WebView webView;
75 77
    private ImageView iv_back, iv_close;
76 78
    private TextView txtTitle, tv_next;
@ -1151,6 +1153,7 @@ public class H5Activity extends Activity implements View.OnClickListener, Platfo
1151 1153
    public void onCancel(Platform platform, int i) {
1152 1154
        Toast.makeText(getApplicationContext(), "分享已取消", Toast.LENGTH_SHORT).show();
1153 1155
    }
1156
1154 1157
    @Override
1155 1158
    public void onRequestPermissionsResult(int requestCode,
1156 1159
                                           @NonNull String[] permissions,
@ -1277,7 +1280,7 @@ public class H5Activity extends Activity implements View.OnClickListener, Platfo
1277 1280
                .canceledOnTouchOutside(false).itemsCallback(new MaterialDialog.ListCallback() {
1278 1281
            @Override
1279 1282
            public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
1280
                if (position == 0){
1283
                if (position == 0) {
1281 1284
                    takeCamera();
1282 1285
                } else if (position == 1) {
1283 1286
                    takePhoto();
@ -1297,19 +1300,18 @@ public class H5Activity extends Activity implements View.OnClickListener, Platfo
1297 1300
    // 拍照
1298 1301
    private void takeCamera() {
1299 1302
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1300
        if (ImageUitl.hasSdcard()) {
1301
            String fileName = "android" + System.currentTimeMillis() / 1000 + ".jpg";
1302
            cameraFilePath = ImageUitl.getPath(Environment.getExternalStorageDirectory() + "/" + "cdz") + "/" + fileName;
1303
            File imageFile = ImageUitl.getFile(cameraFilePath);
1304
            Uri uri = parseUri(imageFile);
1305
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
1306
            try{
1307
                startActivityForResult(intent, FILE_CAMERA_RESULT_CODE);
1308
            } catch (Exception e) {
1309
                e.printStackTrace();
1310
            }
1311 1303
1304
        String fileName = "android" + System.currentTimeMillis() / 1000 + ".jpg";
1305
        cameraFilePath = ImageUitl.getPath(PhotoUtils.CACHE_DIR) + "/" + fileName;
1306
        File imageFile = ImageUitl.getFile(cameraFilePath);
1307
        Uri uri = parseUri(imageFile);
1308
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
1309
        try {
1310
            startActivityForResult(intent, FILE_CAMERA_RESULT_CODE);
1311
        } catch (Exception e) {
1312
            e.printStackTrace();
1312 1313
        }
1314
1313 1315
    }
1314 1316
1315 1317
    private Uri parseUri(File cameraFile) {
@ -1327,7 +1329,8 @@ public class H5Activity extends Activity implements View.OnClickListener, Platfo
1327 1329
    @Override
1328 1330
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
1329 1331
        super.onActivityResult(requestCode, resultCode, data);
1330
        if (null == mOpenFileWebChromeClient.mFilePathCallback && null == mOpenFileWebChromeClient.mFilePathCallbacks) return;
1332
        if (null == mOpenFileWebChromeClient.mFilePathCallback && null == mOpenFileWebChromeClient.mFilePathCallbacks)
1333
            return;
1331 1334
        if (resultCode != RESULT_OK) {
1332 1335
            if (mOpenFileWebChromeClient.mFilePathCallbacks != null) {
1333 1336
                mOpenFileWebChromeClient.mFilePathCallbacks.onReceiveValue(null);
@ -1347,7 +1350,7 @@ public class H5Activity extends Activity implements View.OnClickListener, Platfo
1347 1350
                result = data.getData();
1348 1351
            }
1349 1352
            if (result == null && ImageUitl.hasFile(cameraFilePath)) {
1350
                result = Uri.fromFile(new File(cameraFilePath));
1353
                result = PhotoUtils.parseUri(new File(cameraFilePath));
1351 1354
            }
1352 1355
1353 1356
            if (mOpenFileWebChromeClient.mFilePathCallbacks != null) {
@ -1378,13 +1381,13 @@ public class H5Activity extends Activity implements View.OnClickListener, Platfo
1378 1381
            ClipData clipData = intent.getClipData();
1379 1382
            if (clipData != null) {
1380 1383
                results = new Uri[clipData.getItemCount()];
1381
                for (int i=0;i<clipData.getItemCount();i++) {
1384
                for (int i = 0; i < clipData.getItemCount(); i++) {
1382 1385
                    ClipData.Item item = clipData.getItemAt(i);
1383 1386
                    results[i] = item.getUri();
1384 1387
                }
1385 1388
            }
1386 1389
            if (dataString != null) {
1387
                results = new Uri[] {Uri.parse(dataString)};
1390
                results = new Uri[]{Uri.parse(dataString)};
1388 1391
            }
1389 1392
            mOpenFileWebChromeClient.mFilePathCallbacks.onReceiveValue(results);
1390 1393
            mOpenFileWebChromeClient.mFilePathCallbacks = null;

+ 21 - 19
app/src/main/java/com/electric/chargingpile/activity/HomeWebActivity.java

@ -13,10 +13,12 @@ import android.net.Uri;
13 13
import android.net.http.SslError;
14 14
import android.os.Build;
15 15
import android.os.Bundle;
16
import android.os.Environment;
16
17 17
import android.provider.MediaStore;
18
18 19
import androidx.annotation.NonNull;
19 20
import androidx.core.content.FileProvider;
21
20 22
import android.util.Log;
21 23
import android.view.KeyEvent;
22 24
import android.view.View;
@ -40,6 +42,7 @@ import com.electric.chargingpile.application.MainApplication;
40 42
import com.electric.chargingpile.util.DES3;
41 43
import com.electric.chargingpile.util.ImageUitl;
42 44
import com.electric.chargingpile.util.JsonUtils;
45
import com.electric.chargingpile.util.PhotoUtils;
43 46
import com.umeng.analytics.MobclickAgent;
44 47
45 48
import java.io.File;
@ -56,7 +59,7 @@ import cn.sharesdk.wechat.moments.WechatMoments;
56 59
import pub.devrel.easypermissions.AfterPermissionGranted;
57 60
import pub.devrel.easypermissions.EasyPermissions;
58 61
59
public class HomeWebActivity extends Activity implements View.OnClickListener, PlatformActionListener,EasyPermissions.PermissionCallbacks {
62
public class HomeWebActivity extends Activity implements View.OnClickListener, PlatformActionListener, EasyPermissions.PermissionCallbacks {
60 63
    private WebView webView;
61 64
    private ImageView iv_back, iv_close;
62 65
    private TextView txtTitle, tv_next;
@ -707,6 +710,7 @@ public class HomeWebActivity extends Activity implements View.OnClickListener, P
707 710
        super.onPause();
708 711
        MobclickAgent.onPause(this);
709 712
    }
713
710 714
    @Override
711 715
    public void onRequestPermissionsResult(int requestCode,
712 716
                                           @NonNull String[] permissions,
@ -828,7 +832,7 @@ public class HomeWebActivity extends Activity implements View.OnClickListener, P
828 832
                .canceledOnTouchOutside(false).itemsCallback(new MaterialDialog.ListCallback() {
829 833
            @Override
830 834
            public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
831
                if (position == 0){
835
                if (position == 0) {
832 836
                    takeCamera();
833 837
                } else if (position == 1) {
834 838
                    takePhoto();
@ -848,18 +852,15 @@ public class HomeWebActivity extends Activity implements View.OnClickListener, P
848 852
    // 拍照
849 853
    private void takeCamera() {
850 854
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
851
        if (ImageUitl.hasSdcard()) {
852
            String fileName = "android" + System.currentTimeMillis() / 1000 + ".jpg";
853
            cameraFilePath = ImageUitl.getPath(Environment.getExternalStorageDirectory() + "/" + "cdz") + "/" + fileName;
854
            File imageFile = ImageUitl.getFile(cameraFilePath);
855
            Uri uri = parseUri(imageFile);
856
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
857
            try{
858
                startActivityForResult(intent, FILE_CAMERA_RESULT_CODE);
859
            } catch (Exception e) {
860
                e.printStackTrace();
861
            }
862
855
        String fileName = "android" + System.currentTimeMillis() / 1000 + ".jpg";
856
        cameraFilePath = ImageUitl.getPath(PhotoUtils.CACHE_DIR) + "/" + fileName;
857
        File imageFile = ImageUitl.getFile(cameraFilePath);
858
        Uri uri = parseUri(imageFile);
859
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
860
        try {
861
            startActivityForResult(intent, FILE_CAMERA_RESULT_CODE);
862
        } catch (Exception e) {
863
            e.printStackTrace();
863 864
        }
864 865
    }
865 866
@ -878,7 +879,8 @@ public class HomeWebActivity extends Activity implements View.OnClickListener, P
878 879
    @Override
879 880
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
880 881
        super.onActivityResult(requestCode, resultCode, data);
881
        if (null == mOpenFileWebChromeClient.mFilePathCallback && null == mOpenFileWebChromeClient.mFilePathCallbacks) return;
882
        if (null == mOpenFileWebChromeClient.mFilePathCallback && null == mOpenFileWebChromeClient.mFilePathCallbacks)
883
            return;
882 884
        if (resultCode != RESULT_OK) {
883 885
            if (mOpenFileWebChromeClient.mFilePathCallbacks != null) {
884 886
                mOpenFileWebChromeClient.mFilePathCallbacks.onReceiveValue(null);
@ -898,7 +900,7 @@ public class HomeWebActivity extends Activity implements View.OnClickListener, P
898 900
                result = data.getData();
899 901
            }
900 902
            if (result == null && ImageUitl.hasFile(cameraFilePath)) {
901
                result = Uri.fromFile(new File(cameraFilePath));
903
                result = PhotoUtils.parseUri(new File(cameraFilePath));
902 904
            }
903 905
904 906
            if (mOpenFileWebChromeClient.mFilePathCallbacks != null) {
@ -929,13 +931,13 @@ public class HomeWebActivity extends Activity implements View.OnClickListener, P
929 931
            ClipData clipData = intent.getClipData();
930 932
            if (clipData != null) {
931 933
                results = new Uri[clipData.getItemCount()];
932
                for (int i=0;i<clipData.getItemCount();i++) {
934
                for (int i = 0; i < clipData.getItemCount(); i++) {
933 935
                    ClipData.Item item = clipData.getItemAt(i);
934 936
                    results[i] = item.getUri();
935 937
                }
936 938
            }
937 939
            if (dataString != null) {
938
                results = new Uri[] {Uri.parse(dataString)};
940
                results = new Uri[]{Uri.parse(dataString)};
939 941
            }
940 942
            mOpenFileWebChromeClient.mFilePathCallbacks.onReceiveValue(results);
941 943
            mOpenFileWebChromeClient.mFilePathCallbacks = null;

+ 9 - 6
app/src/main/java/com/electric/chargingpile/activity/HotInfoActivity.java

@ -8,7 +8,6 @@ import android.graphics.Bitmap;
8 8
import android.graphics.drawable.BitmapDrawable;
9 9
import android.net.Uri;
10 10
import android.os.Bundle;
11
import android.os.Environment;
12 11
import android.os.Handler;
13 12
import android.os.Message;
14 13
import android.provider.MediaStore;
@ -41,6 +40,7 @@ import com.electric.chargingpile.util.CheckMobileNum;
41 40
import com.electric.chargingpile.util.DES3;
42 41
import com.electric.chargingpile.util.NetUtil;
43 42
import com.electric.chargingpile.util.OkHttpUtil;
43
import com.electric.chargingpile.util.PhotoUtils;
44 44
import com.electric.chargingpile.util.UploadUtil;
45 45
import com.electric.chargingpile.view.CustomProgressDialog;
46 46
import com.squareup.okhttp.Request;
@ -61,7 +61,10 @@ import java.util.Map;
61 61
62 62
import cn.sharesdk.framework.Platform;
63 63
64
64
/**
65
 * 已废弃,
66
 * */
67
@Deprecated
65 68
public class HotInfoActivity extends Activity implements View.OnClickListener {
66 69
    private EditText address, remark, name, phone, car;
67 70
    private String hotAddress, poi_jing, poi_wei, city, district;
@ -430,8 +433,8 @@ public class HotInfoActivity extends Activity implements View.OnClickListener {
430 433
                    @Override
431 434
                    public void onClick(View view) {
432 435
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
433
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(
434
                                Environment.getExternalStorageDirectory(), "androidapp.jpg")));
436
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, PhotoUtils.parseUri(new File(
437
                               PhotoUtils.CACHE_DIR, "androidapp.jpg")));
435 438
                        ((Activity) mContext).startActivityForResult(intent, 2);
436 439
                        popupWindow.dismiss();
437 440
                    }
@ -597,9 +600,9 @@ public class HotInfoActivity extends Activity implements View.OnClickListener {
597 600
                break;
598 601
            // 如果是调用相机拍照时
599 602
            case 2:
600
                File temp = new File(Environment.getExternalStorageDirectory()
603
                File temp = new File(PhotoUtils.CACHE_DIR
601 604
                        + "/androidapp.jpg");
602
                startPhotoZoom(Uri.fromFile(temp));
605
                startPhotoZoom(PhotoUtils.parseUri(temp));
603 606
                break;
604 607
            // 取得裁剪后的图片
605 608
            case 3:

+ 155 - 72
app/src/main/java/com/electric/chargingpile/activity/MainMapActivity.java

@ -1,8 +1,10 @@
1 1
package com.electric.chargingpile.activity;
2 2
3 3
import android.Manifest;
4
import android.annotation.SuppressLint;
4 5
import android.app.Activity;
5 6
import android.content.BroadcastReceiver;
7
import android.content.ContentResolver;
6 8
import android.content.ContentValues;
7 9
import android.content.Context;
8 10
import android.content.DialogInterface;
@ -29,9 +31,13 @@ import android.os.Message;
29 31
30 32
import androidx.annotation.NonNull;
31 33
import androidx.annotation.Nullable;
34
import androidx.annotation.RequiresApi;
32 35
import androidx.constraintlayout.widget.ConstraintLayout;
33 36
import androidx.core.content.FileProvider;
34 37
38
import android.os.Process;
39
import android.provider.MediaStore;
40
import android.provider.Settings;
35 41
import android.text.TextUtils;
36 42
import android.util.Log;
37 43
import android.view.Gravity;
@ -54,6 +60,7 @@ import android.widget.RelativeLayout;
54 60
import android.widget.TextView;
55 61
import android.widget.Toast;
56 62
63
import com.afollestad.materialdialogs.MaterialDialog;
57 64
import com.alibaba.fastjson.JSON;
58 65
import com.amap.api.location.AMapLocation;
59 66
import com.amap.api.location.AMapLocationClient;
@ -118,22 +125,22 @@ import com.electric.chargingpile.util.BarColorUtil;
118 125
import com.electric.chargingpile.util.DES3;
119 126
import com.electric.chargingpile.util.DES3S;
120 127
import com.electric.chargingpile.util.DensityUtil;
128
import com.electric.chargingpile.util.DownloadUtil;
121 129
import com.electric.chargingpile.util.EventBusUtil;
122 130
import com.electric.chargingpile.util.JsonUtils;
123 131
import com.electric.chargingpile.util.LoadingDialog;
124 132
import com.electric.chargingpile.util.Md5Util;
125 133
import com.electric.chargingpile.util.OkHttpUtil;
134
import com.electric.chargingpile.util.PhotoUtils;
126 135
import com.electric.chargingpile.util.SharedPreferencesUtil;
127 136
import com.electric.chargingpile.util.SystemTypeUtil;
128 137
import com.electric.chargingpile.util.ToastUtil;
129 138
import com.electric.chargingpile.util.Util;
130 139
import com.electric.chargingpile.util.ZhanDBHelper;
131
import com.electric.chargingpile.view.AlertDialog;
132 140
import com.electric.chargingpile.view.AlertDialogCommon;
133 141
import com.electric.chargingpile.view.AlertDialogUpdate;
134 142
import com.electric.chargingpile.view.LocationPermissionsDialog;
135 143
import com.electric.chargingpile.view.NotRegisterDialog;
136
import com.electric.chargingpile.view.PreferentialDialog;
137 144
import com.electric.chargingpile.view.SlideAdView;
138 145
import com.electric.chargingpile.view.UpdateDialog;
139 146
import com.google.gson.Gson;
@ -157,10 +164,13 @@ import org.json.JSONObject;
157 164
import java.io.BufferedReader;
158 165
import java.io.BufferedWriter;
159 166
import java.io.File;
167
import java.io.FileInputStream;
168
import java.io.FileNotFoundException;
160 169
import java.io.FileOutputStream;
161 170
import java.io.IOException;
162 171
import java.io.InputStream;
163 172
import java.io.InputStreamReader;
173
import java.io.OutputStream;
164 174
import java.io.OutputStreamWriter;
165 175
import java.io.PrintWriter;
166 176
import java.net.Socket;
@ -174,6 +184,7 @@ import java.util.HashMap;
174 184
import java.util.List;
175 185
import java.util.Map;
176 186
import java.util.Random;
187
import java.util.concurrent.TimeUnit;
177 188
178 189
import cn.sharesdk.framework.Platform;
179 190
import cn.sharesdk.framework.PlatformActionListener;
@ -182,8 +193,8 @@ import cn.sharesdk.tencent.qq.QQ;
182 193
import cn.sharesdk.wechat.friends.Wechat;
183 194
import cn.sharesdk.wechat.moments.WechatMoments;
184 195
import okhttp3.Call;
196
import okhttp3.OkHttpClient;
185 197
import pub.devrel.easypermissions.AfterPermissionGranted;
186
import pub.devrel.easypermissions.AppSettingsDialog;
187 198
import pub.devrel.easypermissions.EasyPermissions;
188 199
189 200
public class MainMapActivity extends Activity implements LocationSource, AMapLocationListener,
@ -381,6 +392,8 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
381 392
    private static final int RC_CAMERA_PERM = 123;
382 393
    private static final int RC_Location_PERM = 125;
383 394
    private static final int RC_Location_FIRST_PERM = 126;
395
    private static final int RC_READ_EXTERNAL_PERM = 127;
396
    private static final int INSTALL_PERMISS_CODE = 128;
384 397
385 398
    private String adfloatUrl = "";
386 399
    private int mLocationToast=0;
@ -401,7 +414,7 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
401 414
                    String format = data.getString("format");
402 415
                    String f = data.getString("progress");
403 416
                    String s = f.substring(0, f.indexOf("."));
404
                    LogUtils.e(s);
417
//                    LogUtils.e(s);
405 418
406 419
                    updateDialog.updateMsg("当前已下载:" + format);
407 420
                    updateDialog.updateProgress(Integer.parseInt(s));
@ -473,7 +486,7 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
473 486
                                now_versionName = JsonUtils.getKeyResult(android, "versionName");
474 487
                                String[] key = now_versionName.split("\\.");
475 488
                                if (key.length - 1 > 2) {
476
                                    dialogup_other();
489
                                    permissionTask();
477 490
                                } else {
478 491
                                    dialogup();
479 492
                                }
@ -734,7 +747,6 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
734 747
        registerReceiver(networkChangeReceiver, intentFilter);
735 748
736 749
        EventBusUtil.register(this);
737
738 750
        if (MainApplication.ad_link.equals("1")) {
739 751
            againPoint = "1";
740 752
            is_dui = getIntent().getStringExtra("is_dui");
@ -1535,7 +1547,9 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
1535 1547
                                        this,
1536 1548
                                        "为了定位您的位置,推荐充电桩,充电桩位置路线导航需要开启位置权限,是否前往开启?",
1537 1549
                                        RC_Location_FIRST_PERM,
1538
                                        Manifest.permission.ACCESS_FINE_LOCATION);
1550
                                        Manifest.permission.ACCESS_FINE_LOCATION,
1551
                                        Manifest.permission.ACCESS_COARSE_LOCATION
1552
                                        );
1539 1553
1540 1554
                        }).show();
1541 1555
@ -2864,7 +2878,8 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
2864 2878
2865 2879
    private boolean hasLocationPermission() {
2866 2880
        return EasyPermissions.hasPermissions(this,
2867
                Manifest.permission.ACCESS_FINE_LOCATION
2881
                Manifest.permission.ACCESS_FINE_LOCATION,
2882
                Manifest.permission.ACCESS_COARSE_LOCATION
2868 2883
        );
2869 2884
    }
2870 2885
@ -2884,7 +2899,9 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
2884 2899
                    this,
2885 2900
                    "为了定位您的位置,推荐充电桩,充电桩位置路线导航需要开启位置权限,是否前往开启?",
2886 2901
                    RC_Location_PERM,
2887
                    Manifest.permission.ACCESS_FINE_LOCATION);
2902
                    Manifest.permission.ACCESS_FINE_LOCATION,
2903
                    Manifest.permission.ACCESS_COARSE_LOCATION
2904
                    );
2888 2905
        }
2889 2906
    }
2890 2907
@ -3375,6 +3392,8 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
3375 3392
                    aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(screenCity, 14.0f));
3376 3393
                }
3377 3394
            }, 500);
3395
        }else if (resultCode == RESULT_OK && requestCode == INSTALL_PERMISS_CODE){
3396
            permissionTask();
3378 3397
        }
3379 3398
    }
3380 3399
@ -3410,6 +3429,10 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
3410 3429
    }
3411 3430
3412 3431
    private void dialogup_other() {
3432
3433
        now_versionCode="999";
3434
        now_versionName="999";
3435
        title="999";
3413 3436
        int code = Integer.parseInt(now_versionCode);
3414 3437
        if (code - getVersionCode(getApplication()) > 0) {
3415 3438
            alterDialog = new AlertDialogUpdate(MainMapActivity.this);
@ -3422,67 +3445,7 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
3422 3445
                        public void onClick(View v) {
3423 3446
                            showProgressWindow();
3424 3447
                            ToastUtil.showToast(getApplicationContext(), "正在下载中", Toast.LENGTH_SHORT);
3425
                            OkHttpUtils.get().url("http://cdz.evcharge.cc/app/app.apk").build()
3426
                                    .execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "cdz_install") {
3427
                                        @Override
3428
                                        public void inProgress(final float progress, long total) {
3429
3430
                                            NumberFormat numberFormat = NumberFormat.getInstance();
3431
3432
                                            // 设置精确到小数点后2位
3433
3434
                                            numberFormat.setMaximumFractionDigits(2);
3435
                                            String format = numberFormat.format(progress * 100);
3436
3437
                                            Message message = new Message();
3438
                                            message.what = 0x01;
3439
3440
                                            Bundle bundle = new Bundle();
3441
                                            bundle.putString("format", format + "%");
3442
                                            LogUtils.e("当前:" + format);
3443
                                            if (!format.contains(".")) {
3444
                                                bundle.putString("progress", format + ".");
3445
                                            } else {
3446
                                                bundle.putString("progress", format);
3447
                                            }
3448
3449
3450
                                            message.setData(bundle);
3451
                                            myHandler.sendMessage(message);
3452
3453
3454
                                        }
3455
3456
                                        @Override
3457
                                        public void onError(Call call, Exception e) {
3458
//                                            LogUtils.e(e.getMessage());
3459
                                        }
3460
3461
                                        @Override
3462
                                        public void onResponse(File response) {
3463
                                            String path = getDatabasePath("zhan_list").getPath();
3464
                                            com.blankj.utilcode.util.LogUtils.e(path);
3465
                                            AppUtils.cleanAppData(path);
3466
3467
                                            Intent intent = new Intent();
3468
                                            intent.setAction(android.content.Intent.ACTION_VIEW);
3469
                                            Uri uri;
3470
                                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
3471
                                                Uri contentUri = FileProvider.getUriForFile(context,
3472
                                                        context.getApplicationContext().getPackageName() + ".provider",
3473
                                                        response);
3474
                                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3475
                                                intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
3476
                                                intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
3477
                                            } else {
3478
                                                uri = Uri.fromFile(response);
3479
                                                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3480
                                                intent.setDataAndType(uri, "application/vnd.android.package-archive");
3481
                                            }
3482
                                            context.startActivity(intent);
3483
                                            android.os.Process.killProcess(android.os.Process.myPid());
3484
                                        }
3485
                                    });
3448
                            downLoadFile();
3486 3449
                        }
3487 3450
                    }).setNegativeButton("退出", new View.OnClickListener() {
3488 3451
                @Override
@ -3493,12 +3456,104 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
3493 3456
                    editor1.clear();
3494 3457
                    finish();
3495 3458
                    ProfileManager.getInstance().setSearchAddress(getApplicationContext(), "");
3496
                    android.os.Process.killProcess(android.os.Process.myPid());
3459
                    Process.killProcess(Process.myPid());
3497 3460
                }
3498 3461
            }).setCancelable(false).show();
3499 3462
        }
3500 3463
    }
3464
    private void downLoadFile() {
3465
        String url = "http://cdz.evcharge.cc/app/app.apk";
3466
3467
        showProgressWindow();
3468
        ToastUtil.showToast(getApplicationContext(), "正在下载中", Toast.LENGTH_SHORT);
3469
        OkHttpUtils.get().url("http://cdz.evcharge.cc/app/app.apk").build()
3470
                .execute(new FileCallBack(PhotoUtils.DOWNLOADS, "cdz_install") {
3471
                    @Override
3472
                    public void inProgress(final float progress, long total) {
3473
3474
                        NumberFormat numberFormat = NumberFormat.getInstance();
3475
3476
                        // 设置精确到小数点后2位
3477
3478
                        numberFormat.setMaximumFractionDigits(2);
3479
                        String format = numberFormat.format(progress * 100);
3480
3481
                        Message message = new Message();
3482
                        message.what = 0x01;
3483
3484
                        Bundle bundle = new Bundle();
3485
                        bundle.putString("format", format + "%");
3486
//                        LogUtils.e("当前:" + format);
3487
                        if (!format.contains(".")) {
3488
                            bundle.putString("progress", format + ".");
3489
                        } else {
3490
                            bundle.putString("progress", format);
3491
                        }
3492
3493
3494
                        message.setData(bundle);
3495
                        myHandler.sendMessage(message);
3496
3497
3498
                    }
3499
3500
                    @Override
3501
                    public void onError(Call call, Exception e) {
3502
                          LogUtils.e(e.getMessage());
3503
                    }
3504
3505
                    @Override
3506
                    public void onResponse(File response) {
3507
                        String path = getDatabasePath("zhan_list").getPath();
3508
                        com.blankj.utilcode.util.LogUtils.e(path);
3509
                        AppUtils.cleanAppData(path);
3510
                        Log.e("hyc","**------**"+response.getAbsolutePath());
3511
                        Log.e("hyc","**------**"+!response.exists());
3512
                        if (!response.exists()){
3513
                            Toast.makeText(context, "文件不存在", Toast.LENGTH_SHORT).show();
3514
                            return  ;
3515
                        }
3516
3517
                        Intent intent = new Intent();
3518
                        intent.setAction(android.content.Intent.ACTION_VIEW);
3519
                        Uri uri;
3520
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
3521
                            Uri contentUri = FileProvider.getUriForFile(context,
3522
                                    context.getApplicationContext().getPackageName() + ".provider",
3523
                                    response);
3524
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3525
                            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
3526
                            intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
3527
                        } else {
3528
                            uri = Uri.fromFile(response);
3529
                            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3530
                            intent.setDataAndType(uri, "application/vnd.android.package-archive");
3531
                        }
3532
                        context.startActivity(intent);
3533
                        android.os.Process.killProcess(android.os.Process.myPid());
3534
                    }
3535
                });
3536
    }
3537
3538
    @AfterPermissionGranted(RC_READ_EXTERNAL_PERM)
3539
    public void permissionTask() {
3540
        if (isPermissionOK()) {
3541
            dialogup_other();
3542
        } else {
3543
            EasyPermissions.requestPermissions(
3544
                    this, "充电桩想要获取您的图片读取权限,是否允许?",
3545
                    RC_READ_EXTERNAL_PERM,
3546
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
3547
                    Manifest.permission.READ_EXTERNAL_STORAGE);
3548
        }
3549
    }
3501 3550
3551
    private boolean isPermissionOK() {
3552
        return EasyPermissions.hasPermissions(this,
3553
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
3554
                Manifest.permission.READ_EXTERNAL_STORAGE
3555
        );
3556
    }
3502 3557
    public static int getVersionCode(Context context)//获取版本号(内部识别号)
3503 3558
    {
3504 3559
        try {
@ -3921,6 +3976,7 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
3921 3976
    }
3922 3977
3923 3978
3979
    @SuppressLint("Range")
3924 3980
    private void getZhanListData(int level) {
3925 3981
        aMap.clear();
3926 3982
        ZhanDBHelper dbHelper = new ZhanDBHelper(this);
@ -5882,6 +5938,33 @@ public class MainMapActivity extends Activity implements LocationSource, AMapLoc
5882 5938
    }
5883 5939
5884 5940
5885
5941
    /**
5942
     * 8.0以上系统设置安装未知来源权限
5943
     */
5944
    public void setInstallPermission(){
5945
        boolean haveInstallPermission;
5946
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
5947
            //先判断是否有安装未知来源应用的权限
5948
            haveInstallPermission = getPackageManager().canRequestPackageInstalls();
5949
            if(!haveInstallPermission){
5950
                //弹框提示用户手动打开
5951
                    AlertDialogCommon  alterDialog = new AlertDialogCommon(MainMapActivity.this);
5952
                    //此方法需要API>=26才能使用
5953
                    alterDialog.builder()
5954
                            .setTitle("安装权限")
5955
                            .setMsg("需要打开允许来自此来源,请去设置中开启此权限")
5956
                            .setCancelable(false)
5957
                            .setPositiveButton("确定", v->{
5958
                                Uri packageURI = Uri.parse("package:"+getPackageName());
5959
                                Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,packageURI);
5960
                                startActivityForResult(intent, INSTALL_PERMISS_CODE);
5961
                            }).show();
5962
            }else{
5963
                permissionTask();
5964
            }
5965
        }else{
5966
            permissionTask();
5967
        }
5968
    }
5886 5969
5887 5970
}

+ 5 - 48
app/src/main/java/com/electric/chargingpile/activity/MyWebViewActivity.java

@ -18,7 +18,6 @@ import android.net.Uri;
18 18
import android.net.http.SslError;
19 19
import android.os.Build;
20 20
import android.os.Bundle;
21
import android.os.Environment;
22 21
import android.os.Handler;
23 22
import android.provider.MediaStore;
24 23
import android.text.TextUtils;
@ -65,6 +64,7 @@ import com.electric.chargingpile.util.ImageUitl;
65 64
import com.electric.chargingpile.util.JsonUtils;
66 65
import com.electric.chargingpile.util.LoadingDialog;
67 66
import com.electric.chargingpile.util.PhoneUtils;
67
import com.electric.chargingpile.util.PhotoUtils;
68 68
import com.electric.chargingpile.util.ToastUtil;
69 69
import com.electric.chargingpile.util.Util;
70 70
import com.electric.chargingpile.view.AlertDialogTwo;
@ -245,40 +245,9 @@ public class MyWebViewActivity extends Activity implements PlatformActionListene
245 245
    }
246 246
247 247
    private void saveImage(Bitmap resource) {
248
        String saveImagePath = null;
249
        String imageFileName = "d1ev_" + PhoneUtils.getGUID() + ".png";
250
        File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "d1ev");
251
        boolean success = true;
252
        if (!storageDir.exists()) {
253
            success = storageDir.mkdir();
254
        }
255
256
        if (success) {
257
            File imageFile = new File(storageDir, imageFileName);
258
            saveImagePath = imageFile.getAbsolutePath();
259
            try {
260
                OutputStream outputStream = new FileOutputStream(imageFile);
261
                resource.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
262
                outputStream.close();
263
            } catch (Exception e) {
264
                ToastUtil.showToast(MyWebViewActivity.this, "保存图像失败", Toast.LENGTH_SHORT);
265
                e.printStackTrace();
266
            }
267
268
            galleryAddPic(saveImagePath);
269
        } else {
270
            ToastUtil.showToast(MyWebViewActivity.this, "保存图像失败", Toast.LENGTH_SHORT);
271
        }
248
        PhotoUtils.saveBitmap(this,resource);
272 249
    }
273 250
274
    private void galleryAddPic(String imagePath) {
275
        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
276
        File file = new File(imagePath);
277
        Uri uri = Uri.fromFile(file);
278
        intent.setData(uri);
279
        sendBroadcast(intent);
280
        ToastUtil.showToast(MyWebViewActivity.this, "图像已成功保存到相册", Toast.LENGTH_SHORT);
281
    }
282 251
283 252
284 253
    // 93 3.5.5 小程序埋点
@ -1496,9 +1465,9 @@ public class MyWebViewActivity extends Activity implements PlatformActionListene
1496 1465
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1497 1466
        if (ImageUitl.hasSdcard()) {
1498 1467
            String fileName = "android" + System.currentTimeMillis() / 1000 + ".jpg";
1499
            cameraFilePath = ImageUitl.getPath(Environment.getExternalStorageDirectory() + "/" + "cdz") + "/" + fileName;
1468
            cameraFilePath = ImageUitl.getPath(PhotoUtils.CACHE_DIR) + "/" + fileName;
1500 1469
            File imageFile = ImageUitl.getFile(cameraFilePath);
1501
            Uri uri = parseUri(imageFile);
1470
            Uri uri =PhotoUtils.parseUri(imageFile);
1502 1471
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
1503 1472
            try {
1504 1473
                startActivityForResult(intent, FILE_CAMERA_RESULT_CODE);
@ -1509,18 +1478,6 @@ public class MyWebViewActivity extends Activity implements PlatformActionListene
1509 1478
        }
1510 1479
    }
1511 1480
1512
    private Uri parseUri(File cameraFile) {
1513
        Uri imageUri;
1514
        String authority = getPackageName() + ".provider";
1515
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
1516
            //通过FileProvider创建一个content类型的Uri
1517
            imageUri = FileProvider.getUriForFile(getApplicationContext(), authority, cameraFile);
1518
        } else {
1519
            imageUri = Uri.fromFile(cameraFile);
1520
        }
1521
        return imageUri;
1522
    }
1523
1524 1481
    public class MyWebViewClient extends WebViewClient {
1525 1482
        @Override
1526 1483
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
@ -1593,7 +1550,7 @@ public class MyWebViewActivity extends Activity implements PlatformActionListene
1593 1550
                result = data.getData();
1594 1551
            }
1595 1552
            if (result == null && ImageUitl.hasFile(cameraFilePath)) {
1596
                result = Uri.fromFile(new File(cameraFilePath));
1553
                result = PhotoUtils.parseUri(new File(cameraFilePath));
1597 1554
            }
1598 1555
1599 1556
            if (mOpenFileWebChromeClient.mFilePathCallbacks != null) {

+ 2 - 2
app/src/main/java/com/electric/chargingpile/activity/NewSelectCityActivity.java

@ -609,7 +609,7 @@ public class NewSelectCityActivity extends AppCompatActivity implements ISelectC
609 609
    }
610 610
611 611
    private boolean hasLocationPermission() {
612
        return EasyPermissions.hasPermissions(this, Manifest.permission.ACCESS_FINE_LOCATION);
612
        return EasyPermissions.hasPermissions(this, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION);
613 613
    }
614 614
615 615
    @AfterPermissionGranted(RC_Location_PERM)
@ -621,7 +621,7 @@ public class NewSelectCityActivity extends AppCompatActivity implements ISelectC
621 621
                    this,
622 622
                    "为了定位您的位置,推荐充电桩,充电桩位置路线导航需要开启位置权限,是否前往开启?",
623 623
                    RC_Location_PERM,
624
                    Manifest.permission.ACCESS_FINE_LOCATION);
624
                    Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION);
625 625
        }
626 626
    }
627 627
}

+ 57 - 218
app/src/main/java/com/electric/chargingpile/activity/PrivateZhuangInfoActivity.java

@ -1,7 +1,6 @@
1 1
package com.electric.chargingpile.activity;
2 2
3 3
import android.Manifest;
4
import android.annotation.SuppressLint;
5 4
import android.app.Activity;
6 5
import android.app.ProgressDialog;
7 6
import android.app.TimePickerDialog;
@ -9,17 +8,13 @@ import android.content.Context;
9 8
import android.content.Intent;
10 9
import android.graphics.Bitmap;
11 10
import android.graphics.BitmapFactory;
12
import android.graphics.Color;
13 11
import android.graphics.Matrix;
14 12
import android.graphics.drawable.BitmapDrawable;
15
import android.graphics.drawable.ColorDrawable;
16 13
import android.graphics.drawable.Drawable;
17
import android.net.Uri;
14
import android.os.Build;
18 15
import android.os.Bundle;
19
import android.os.Environment;
20 16
import android.os.Handler;
21 17
import android.os.Message;
22
import android.provider.MediaStore;
23 18
import android.util.Base64;
24 19
import android.util.Log;
25 20
import android.view.Gravity;
@ -29,12 +24,8 @@ import android.view.Menu;
29 24
import android.view.MenuItem;
30 25
import android.view.View;
31 26
import android.view.ViewGroup;
32
import android.widget.AdapterView;
33
import android.widget.AdapterView.OnItemClickListener;
34
import android.widget.BaseAdapter;
35 27
import android.widget.Button;
36 28
import android.widget.EditText;
37
import android.widget.GridView;
38 29
import android.widget.ImageView;
39 30
import android.widget.LinearLayout;
40 31
import android.widget.PopupWindow;
@ -61,32 +52,31 @@ import com.electric.chargingpile.application.MainApplication;
61 52
import com.electric.chargingpile.data.Pic;
62 53
import com.electric.chargingpile.data.PrivateZhuang;
63 54
import com.electric.chargingpile.data.Zhan;
55
import com.electric.chargingpile.engine.GlideEngine;
64 56
import com.electric.chargingpile.util.BarColorUtil;
65 57
import com.electric.chargingpile.util.Bimp;
66 58
import com.electric.chargingpile.util.CheckMobileNum;
67 59
import com.electric.chargingpile.util.DensityUtil;
68
import com.electric.chargingpile.util.FileUtils;
69 60
import com.electric.chargingpile.util.ImageItem;
70
import com.electric.chargingpile.util.ImageUtils;
71 61
import com.electric.chargingpile.util.JsonUtils;
72 62
import com.electric.chargingpile.util.OkHttpUtil;
73 63
import com.electric.chargingpile.util.PublicWay;
74 64
import com.electric.chargingpile.util.Res;
75
import com.electric.chargingpile.util.ScreenUtils;
76 65
import com.electric.chargingpile.util.ToastUtil;
77 66
import com.electric.chargingpile.util.UploadUtil;
67
import com.electric.chargingpile.util.Util;
78 68
import com.electric.chargingpile.view.CustomProgressDialog;
69
import com.luck.picture.lib.PictureSelector;
70
import com.luck.picture.lib.animators.AnimationType;
71
import com.luck.picture.lib.config.PictureConfig;
72
import com.luck.picture.lib.config.PictureMimeType;
73
import com.luck.picture.lib.entity.LocalMedia;
79 74
import com.squareup.okhttp.Request;
80 75
import com.squareup.okhttp.Response;
81
import com.zhihu.matisse.Matisse;
82
import com.zhihu.matisse.MimeType;
83
import com.zhihu.matisse.engine.impl.GlideEngine;
84
import com.zhihu.matisse.internal.entity.CaptureStrategy;
85 76
86 77
import org.json.JSONException;
87 78
import org.json.JSONObject;
88 79
89
import java.io.ByteArrayInputStream;
90 80
import java.io.ByteArrayOutputStream;
91 81
import java.io.File;
92 82
import java.io.FileNotFoundException;
@ -125,9 +115,6 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
125 115
    private TimePickerDialog tpd_close = null;
126 116
    private String camePath;//拍照路径
127 117
128
    private static final String PHOTO_FILE_NAME = "android.jpg";
129
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
130
    private File tempFile;
131 118
    private static final int PHOTO_REQUEST_CAMERA = 1;
132 119
    private static final int PHOTO_REQUEST_GALLERY = 2;
133 120
    private static final int PHOTO_REQUEST_CUT = 3;
@ -176,8 +163,7 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
176 163
    private RadioGroup rg_claimtype, rg_park;
177 164
    public static Bitmap bimap;
178 165
    private View parentView;
179
    private PopupWindow pop = null;
180
    private LinearLayout ll_popup;
166
181 167
    private TextView open_time, close_time, share_list;
182 168
    private RelativeLayout rl_address;
183 169
    private String tag, id, zhan_name, zhan_address, poi_jing, poi_wei, fast_num, slow_num,
@ -265,9 +251,6 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
265 251
    protected void onCreate(Bundle savedInstanceState) {
266 252
        super.onCreate(savedInstanceState);
267 253
        initDate();
268
269
270
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
271 254
        Res.init(this);
272 255
        bimap = BitmapFactory.decodeResource(getResources(), R.drawable.addpic65);
273 256
        PublicWay.activityList.add(this);
@ -311,58 +294,6 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
311 294
        selectBitmap[1] = null;
312 295
        selectBitmap[2] = null;
313 296
314
        pop = new PopupWindow(PrivateZhuangInfoActivity.this);
315
316
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
317
318
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
319
320
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
321
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
322
        pop.setBackgroundDrawable(new BitmapDrawable());
323
        pop.setFocusable(true);
324
        pop.setOutsideTouchable(true);
325
        pop.setContentView(view);
326
327
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
328
        Button bt1 = (Button) view.findViewById(R.id.item_popupwindows_camera);
329
        Button bt2 = (Button) view.findViewById(R.id.item_popupwindows_Photo);
330
        Button bt3 = (Button) view.findViewById(R.id.item_popupwindows_cancel);
331
        parent.setOnClickListener(new View.OnClickListener() {
332
            @Override
333
            public void onClick(View v) {
334
                // TODO Auto-generated method stub
335
                pop.dismiss();
336
                ll_popup.clearAnimation();
337
            }
338
        });
339
        bt1.setOnClickListener(new View.OnClickListener() {
340
            public void onClick(View v) {
341
                pop.dismiss();
342
                ll_popup.clearAnimation();
343
                if (MainScanActivity.isCameraUseable()) {
344
                    photo();
345
                } else {
346
                    ToastUtil.showToast(getApplicationContext(), "您当前关闭了调用摄像头权限", Toast.LENGTH_SHORT);
347
                }
348
            }
349
        });
350
        bt2.setOnClickListener(new View.OnClickListener() {
351
            public void onClick(View v) {
352
                Intent intent = new Intent(PrivateZhuangInfoActivity.this,
353
                        AlbumActivity.class);
354
                startActivity(intent);
355
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
356
                pop.dismiss();
357
                ll_popup.clearAnimation();
358
            }
359
        });
360
        bt3.setOnClickListener(new View.OnClickListener() {
361
            public void onClick(View v) {
362
                pop.dismiss();
363
                ll_popup.clearAnimation();
364
            }
365
        });
366 297
367 298
        take_image_0 = findViewById(R.id.take_image_0);
368 299
        take_image_1 = findViewById(R.id.take_image_1);
@ -392,6 +323,7 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
392 323
     * 调用图库选择
393 324
     */
394 325
    private void callGallery() {
326
/*
395 327
        Matisse.from(PrivateZhuangInfoActivity.this)
396 328
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
397 329
                .showSingleMediaType(true)
@ -401,6 +333,27 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
401 333
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
402 334
                .imageEngine(new GlideEngine())
403 335
                .forResult(REQUEST_CODE_CHOOSE);
336
*/
337
        PictureSelector.create(this)
338
                .openGallery(PictureMimeType.ofImage())
339
                .selectionMode(PictureConfig.SINGLE)
340
                .isSingleDirectReturn(true)
341
                .isCompress(true)//是否压缩
342
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
343
                .isGif(true)//是否显示gif
344
                .isAndroidQTransform(true)
345
                .imageEngine(GlideEngine.createGlideEngine())
346
                .isWeChatStyle(false)// 是否开启微信图片选择风格
347
                .isUseCustomCamera(false)// 是否使用自定义相机
348
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
349
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
350
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
351
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
352
                .imageSpanCount(4)// 每行显示个数
353
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
354
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
355
                .forResult(REQUEST_CODE_CHOOSE);
356
404 357
    }
405 358
406 359
    @Override
@ -436,21 +389,33 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
436 389
            @Override
437 390
            public void subscribe(ObservableEmitter<String> subscriber) {
438 391
                try {
439
                    List<Uri> uriList = Matisse.obtainResult(data);
440
                    Uri uri = uriList.get(0);
441
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
442
                    File file = FileUtils.from(PrivateZhuangInfoActivity.this, uri);
443
444
                    bitmap = FileUtils.rotateIfRequired(file, bitmap);
445
                    bitmap = imageZoom(bitmap);
446
447
                    ImageItem takePhoto = new ImageItem();
448
                    takePhoto.setBitmap(bitmap);
449
                    selectBitmap[selectIndex] = takePhoto;
450
                    isTakePhoto = true;
392
                    List<LocalMedia> mediaList = PictureSelector.obtainMultipleResult(data);
393
                    if (mediaList!=null && mediaList.size()>0){
394
                     /*   List<Uri> uriList = Matisse.obtainResult(data);
395
                        Uri uri = uriList.get(0);
396
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
397
                        File file = FileUtils.from(PrivateZhuangInfoActivity.this, uri);
398
399
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
400
                        bitmap = imageZoom(bitmap);*/
401
402
                        String path="";
403
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
404
                            path= mediaList.get(0).getAndroidQToPath();
405
                        }else{
406
                            path=mediaList.get(0).getPath();
407
                        }
408
                        ImageItem takePhoto = new ImageItem();
409
                        takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
410
                        selectBitmap[selectIndex] = takePhoto;
411
                        isTakePhoto = true;
412
413
                        subscriber.onNext("");
414
                        subscriber.onComplete();
415
                    }else{
416
                        subscriber.onError(new Exception(""));
417
                    }
451 418
452
                    subscriber.onNext("");
453
                    subscriber.onComplete();
454 419
                } catch (Exception e) {
455 420
                    e.printStackTrace();
456 421
                    subscriber.onError(e);
@ -1104,13 +1069,6 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
1104 1069
1105 1070
    private static final int TAKE_PICTURE = 0x000001;
1106 1071
1107
    public void photo() {
1108
        if (hasSdcard()) {
1109
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1110
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
1111
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
1112
        }
1113
    }
1114 1072
1115 1073
    @Override
1116 1074
    protected void onDestroy() {
@ -1119,125 +1077,6 @@ public class PrivateZhuangInfoActivity extends Activity implements View.OnClickL
1119 1077
        super.onDestroy();
1120 1078
    }
1121 1079
1122
1123
    private Bitmap compressBmpFromBmp(Bitmap image) {
1124
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1125
        int options = 100;
1126
        image.compress(Bitmap.CompressFormat.JPEG, 60, baos);
1127
        while (baos.toByteArray().length / 1024 > 200) {
1128
            baos.reset();
1129
            options -= 10;
1130
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
1131
        }
1132
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
1133
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
1134
        return bitmap;
1135
    }
1136
1137
1138
    private void crop(Uri uri, Uri cutImgUri) {
1139
        Intent intent = new Intent("com.android.camera.action.CROP");
1140
        intent.setDataAndType(uri, "image/*");
1141
        intent.putExtra("crop", "true");
1142
        intent.putExtra("outputFormat", "JPEG");
1143
        intent.putExtra("noFaceDetection", true);// ȡ������ʶ��
1144
        intent.putExtra("return-data", false);// true:������uri��false������uri
1145
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cutImgUri);//д���ȡ��ͼƬ
1146
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
1147
    }
1148
1149
    private boolean hasSdcard() {
1150
        if (Environment.getExternalStorageState().equals(
1151
                Environment.MEDIA_MOUNTED)) {
1152
            return true;
1153
        } else {
1154
            return false;
1155
        }
1156
    }
1157
1158
    private static String getPath(String path) {
1159
        File f = new File(path);
1160
        if (!f.exists()) {
1161
            f.mkdirs();
1162
        }
1163
        return f.getAbsolutePath();
1164
    }
1165
1166
    private File getFile(String path) {
1167
        File f = new File(path);
1168
        if (!f.exists()) {
1169
            try {
1170
                f.createNewFile();
1171
            } catch (IOException e) {
1172
                e.printStackTrace();
1173
            }
1174
        }
1175
        return f;
1176
    }
1177
1178
    public Bitmap decodeUriAsBitmap(Uri uri) {
1179
        Bitmap bitmap = null;
1180
        try {
1181
            bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri));
1182
        } catch (FileNotFoundException e) {
1183
            e.printStackTrace();
1184
            return null;
1185
        }
1186
        return bitmap;
1187
    }
1188
1189
    private Bitmap comp(Bitmap image) {
1190
1191
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1192
        image.compress(Bitmap.CompressFormat.JPEG, 30, baos);
1193
        if (baos.toByteArray().length / 1024 > 1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
1194
            baos.reset();//重置baos即清空baos
1195
            image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中
1196
        }
1197
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
1198
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
1199
        //开始读入图片,此时把options.inJustDecodeBounds 设回true了
1200
        newOpts.inJustDecodeBounds = true;
1201
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
1202
        newOpts.inJustDecodeBounds = false;
1203
        int w = newOpts.outWidth;
1204
        int h = newOpts.outHeight;
1205
        //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
1206
        float hh = 800f;//这里设置高度为800f
1207
        float ww = 480f;//这里设置宽度为480f
1208
        //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
1209
        int be = 1;//be=1表示不缩放
1210
        if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
1211
            be = (int) (newOpts.outWidth / ww);
1212
        } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
1213
            be = (int) (newOpts.outHeight / hh);
1214
        }
1215
        if (be <= 0)
1216
            be = 1;
1217
        newOpts.inSampleSize = be;//设置缩放比例
1218
        newOpts.inPreferredConfig = Bitmap.Config.RGB_565;//降低图片从ARGB888到RGB565
1219
        //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
1220
        isBm = new ByteArrayInputStream(baos.toByteArray());
1221
        bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
1222
        return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
1223
    }
1224
1225
1226
    private Bitmap compressImage(Bitmap image) {
1227
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1228
        image.compress(Bitmap.CompressFormat.JPEG, 80, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
1229
        int options = 70;
1230
        while (baos.toByteArray().length / 1024 > 300) {    //循环判断如果压缩后图片是否大于100kb,大于继续压缩
1231
            baos.reset();//重置baos即清空baos
1232
            options -= 10;//每次都减少10
1233
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
1234
1235
        }
1236
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
1237
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
1238
        return bitmap;
1239
    }
1240
1241 1080
    private Bitmap imageZoom(Bitmap bm) {
1242 1081
        // 图片允许最大空间 单位:KB
1243 1082
        double maxSize = 200.00;

+ 2 - 0
app/src/main/java/com/electric/chargingpile/activity/PublishItemsActivity.java

@ -22,7 +22,9 @@ import com.umeng.analytics.MobclickAgent;
22 22
/**
23 23
 * @author dxh
24 24
 * 发布类型选择页
25
 * 已废弃,不在维护。
25 26
 */
27
@Deprecated
26 28
public class PublishItemsActivity extends AppCompatActivity implements View.OnClickListener {
27 29
    private static final String TAG = "PublishItemsActivity";
28 30

+ 69 - 120
app/src/main/java/com/electric/chargingpile/activity/PublishPicTopicActivity.java

@ -16,7 +16,7 @@ import android.graphics.drawable.ColorDrawable;
16 16
import android.net.Uri;
17 17
import android.os.Build;
18 18
import android.os.Bundle;
19
import android.os.Environment;
19
20 20
import android.os.Handler;
21 21
import android.os.Message;
22 22
import android.provider.MediaStore;
@ -54,6 +54,7 @@ import com.electric.chargingpile.data.ChatRecommendBean;
54 54
import com.electric.chargingpile.data.PhotoUploadResult;
55 55
import com.electric.chargingpile.data.PublishItemSerializable;
56 56
import com.electric.chargingpile.data.UploadPic;
57
import com.electric.chargingpile.engine.GlideEngine;
57 58
import com.electric.chargingpile.util.BarColorUtil;
58 59
import com.electric.chargingpile.util.Base64;
59 60
import com.electric.chargingpile.util.Bimp;
@ -68,16 +69,18 @@ import com.electric.chargingpile.util.PublicWay;
68 69
import com.electric.chargingpile.util.Res;
69 70
import com.electric.chargingpile.util.ToastUtil;
70 71
import com.electric.chargingpile.util.Util;
72
import com.luck.picture.lib.PictureSelector;
73
import com.luck.picture.lib.animators.AnimationType;
74
import com.luck.picture.lib.config.PictureConfig;
75
import com.luck.picture.lib.config.PictureMimeType;
76
import com.luck.picture.lib.entity.LocalMedia;
71 77
import com.luck.picture.lib.tools.ScreenUtils;
72 78
import com.umeng.analytics.MobclickAgent;
73 79
import com.upyun.library.common.ParallelUploader;
74 80
import com.upyun.library.common.UploadEngine;
75 81
import com.upyun.library.listener.UpCompleteListener;
76 82
import com.upyun.library.listener.UpProgressListener;
77
import com.zhihu.matisse.Matisse;
78
import com.zhihu.matisse.MimeType;
79
import com.zhihu.matisse.engine.impl.GlideEngine;
80
import com.zhihu.matisse.internal.entity.CaptureStrategy;
83
81 84
import com.zhy.http.okhttp.OkHttpUtils;
82 85
import com.zhy.http.okhttp.callback.StringCallback;
83 86
@ -104,17 +107,15 @@ import pub.devrel.easypermissions.EasyPermissions;
104 107
/**
105 108
 * @desc : 发布话题
106 109
 */
110
@Deprecated
107 111
public class PublishPicTopicActivity extends Activity implements OnClickListener, EasyPermissions.PermissionCallbacks {
108 112
    private static final String TAG = "PublishPicTopicActivity";
109 113
    private static final int PIC_NUM = 9;
110 114
    private ImageView ivBack;
111 115
    private TextView tv_right;
112
    private static String PHOTO_FILE_NAME = "";
113
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
114 116
    private GridView noScrollgridview;
115
    private PopupWindow pop = null;
116
    private LinearLayout ll_popup;
117
    private File tempFile;
117
118
118 119
    Bitmap bm = null;
119 120
    private static final int PHOTO_REQUEST_CAMERA = 1;
120 121
    private static final int PHOTO_REQUEST_GALLERY = 2;
@ -153,7 +154,7 @@ public class PublishPicTopicActivity extends Activity implements OnClickListener
153 154
154 155
    public static final int REQUEST_CODE_CHOOSE = 342;
155 156
156
157
    private List<LocalMedia> mSelectionData =new ArrayList<LocalMedia>();
157 158
    @Override
158 159
    protected void onCreate(Bundle savedInstanceState) {
159 160
        super.onCreate(savedInstanceState);
@ -163,9 +164,6 @@ public class PublishPicTopicActivity extends Activity implements OnClickListener
163 164
        initView();
164 165
        Res.init(this);
165 166
        PublicWay.activityList.add(this);
166
        long appTime1 = System.currentTimeMillis() / 1000;
167
        PHOTO_FILE_NAME = "android" + appTime1 + ".jpg";
168
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
169 167
        dialog = new LoadingDialog(this);
170 168
        dialog.setCanceledOnTouchOutside(false);
171 169
        Init();
@ -386,77 +384,8 @@ public class PublishPicTopicActivity extends Activity implements OnClickListener
386 384
        return f;
387 385
    }
388 386
389
    private static String getPath(String path) {
390
        File f = new File(path);
391
        if (!f.exists()) {
392
            f.mkdirs();
393
        }
394
        return f.getAbsolutePath();
395
    }
396
397
    private boolean hasSdcard() {
398
        if (Environment.getExternalStorageState().equals(
399
                Environment.MEDIA_MOUNTED)) {
400
            return true;
401
        } else {
402
            return false;
403
        }
404
    }
405 387
406 388
    public void Init() {
407
        pop = new PopupWindow(PublishPicTopicActivity.this);
408
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
409
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
410
411
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
412
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
413
        pop.setBackgroundDrawable(new BitmapDrawable());
414
        pop.setFocusable(true);
415
        pop.setOutsideTouchable(true);
416
        pop.setContentView(view);
417
418
419
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
420
        Button bt1 = (Button) view.findViewById(R.id.item_popupwindows_camera);
421
        Button bt2 = (Button) view.findViewById(R.id.item_popupwindows_Photo);
422
        Button bt3 = (Button) view.findViewById(R.id.item_popupwindows_cancel);
423
        parent.setOnClickListener(new OnClickListener() {
424
425
            @Override
426
            public void onClick(View v) {
427
                // TODO Auto-generated method stub
428
                pop.dismiss();
429
                ll_popup.clearAnimation();
430
            }
431
        });
432
        bt1.setOnClickListener(new OnClickListener() {
433
            public void onClick(View v) {
434
                pop.dismiss();
435
                ll_popup.clearAnimation();
436
                if (MainScanActivity.isCameraUseable()) {
437
                    photo();
438
                } else {
439
                    ToastUtil.showToast(getApplicationContext(), "您当前关闭了调用摄像头权限", Toast.LENGTH_SHORT);
440
                }
441
            }
442
        });
443
        bt2.setOnClickListener(new OnClickListener() {
444
            public void onClick(View v) {
445
                Intent intent = new Intent(PublishPicTopicActivity.this,
446
                        AlbumActivityFeedback.class);
447
                startActivity(intent);
448
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
449
                pop.dismiss();
450
                ll_popup.clearAnimation();
451
            }
452
        });
453
        bt3.setOnClickListener(new OnClickListener() {
454
            public void onClick(View v) {
455
                pop.dismiss();
456
                ll_popup.clearAnimation();
457
            }
458
        });
459
460 389
        noScrollgridview = (GridView) findViewById(R.id.noScrollgridview);
461 390
        noScrollgridview.setSelector(new ColorDrawable(Color.TRANSPARENT));
462 391
        adapter = new GridAdapter(this);
@ -487,15 +416,36 @@ public class PublishPicTopicActivity extends Activity implements OnClickListener
487 416
     */
488 417
    private void callGallery() {
489 418
        MobclickAgent.onEvent(getApplicationContext(), "1024");
490
        Matisse.from(PublishPicTopicActivity.this)
491
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
492
                .showSingleMediaType(true)
493
                .countable(true)
494
                .maxSelectable(PIC_NUM - Bimp.tempSelectBitmap.size())
495
                .capture(true)
496
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
497
                .imageEngine(new GlideEngine())
419
//        Matisse.from(PublishPicTopicActivity.this)
420
//                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
421
//                .showSingleMediaType(true)
422
//                .countable(true)
423
//                .maxSelectable(PIC_NUM - Bimp.tempSelectBitmap.size())
424
//                .capture(true)
425
//                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
426
//                .imageEngine(new GlideEngine())
427
//                .forResult(REQUEST_CODE_CHOOSE);
428
        PictureSelector.create(this)
429
                .openGallery(PictureMimeType.ofImage())
430
                .maxSelectNum(PIC_NUM)
431
                .selectionData(mSelectionData)//是否传入已选图片
432
                .selectionMode(PictureConfig.MULTIPLE)
433
                .isCompress(true)//是否压缩
434
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
435
                .isGif(true)//是否显示gif
436
                .isAndroidQTransform(true)
437
                .imageEngine(GlideEngine.createGlideEngine())
438
                .isWeChatStyle(false)// 是否开启微信图片选择风格
439
                .isUseCustomCamera(false)// 是否使用自定义相机
440
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
441
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
442
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
443
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
444
                .imageSpanCount(4)// 每行显示个数
445
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
446
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
498 447
                .forResult(REQUEST_CODE_CHOOSE);
448
499 449
    }
500 450
501 451
    @Override
@ -533,30 +483,38 @@ public class PublishPicTopicActivity extends Activity implements OnClickListener
533 483
            @Override
534 484
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
535 485
                try {
536
                    List<Uri> uriList = Matisse.obtainResult(data);
486
//                    List<Uri> uriList = Matisse.obtainResult(data);
487
                    mSelectionData= PictureSelector.obtainMultipleResult(data);
488
537 489
                    int i = 0;
538
                    for (Uri uri : uriList) {
490
                    for (LocalMedia localMedia : mSelectionData) {
539 491
                        i++;
540
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
541
                        File file = FileUtils.from(PublishPicTopicActivity.this, uri);
542
543
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
544
                        bitmap = imageZoom(bitmap);
492
//                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
493
//                        File file = FileUtils.from(PublishPicTopicActivity.this, uri);
494
//
495
//                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
496
//                        bitmap = imageZoom(bitmap);
545 497
                        ImageItem takePhoto = new ImageItem();
546
                        String deviceId = JPushInterface.getUdid(MainApplication.context);
547
                        takePhoto.fName = DateUtils.getSimpleCurrentDate();
548
                        if (TextUtils.isEmpty(deviceId)) {
549
                            takePhoto.fName += "_" + Util.getRandom(15);
550
                        } else {
551
                            takePhoto.fName += "_" + deviceId;
498
//                        String deviceId = JPushInterface.getUdid(MainApplication.context);
499
//                        takePhoto.fName = DateUtils.getSimpleCurrentDate();
500
//                        if (TextUtils.isEmpty(deviceId)) {
501
//                            takePhoto.fName += "_" + Util.getRandom(15);
502
//                        } else {
503
//                            takePhoto.fName += "_" + deviceId;
504
//                        }
505
//                        takePhoto.fName += "_00" + i;
506
//
507
//                        String filePath = file.getAbsolutePath();
508
//                        String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
509
//                        takePhoto.fName += "." + suffix;
510
                        String path="";
511
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
512
                            path= localMedia.getAndroidQToPath();
513
                        }else{
514
                            path=localMedia.getPath();
552 515
                        }
553
                        takePhoto.fName += "_00" + i;
554
555
                        String filePath = file.getAbsolutePath();
556
                        String suffix = filePath.substring(filePath.lastIndexOf(".") + 1);
557
                        takePhoto.fName += "." + suffix;
558
                        takePhoto.setBitmap(bitmap);
559
                        takePhoto.setFile(file);
516
                        takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
517
                        takePhoto.setFile(new File(path));
560 518
                        Bimp.tempSelectBitmap.add(takePhoto);
561 519
                        subscriber.onNext("");
562 520
                    }
@ -738,15 +696,6 @@ public class PublishPicTopicActivity extends Activity implements OnClickListener
738 696
        }
739 697
    }
740 698
741
    public void photo() {
742
        if (hasSdcard()) {
743
            int currentapiVersion = Build.VERSION.SDK_INT;
744
            Log.e("currentapiVersion", "currentapiVersion====>" + currentapiVersion);
745
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
746
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
747
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
748
        }
749
    }
750 699
751 700
    @Override
752 701
    protected void onRestart() {

+ 5 - 5
app/src/main/java/com/electric/chargingpile/activity/PublishVideoTopicActivity.java

@ -11,7 +11,6 @@ import android.content.pm.ActivityInfo;
11 11
import android.graphics.Color;
12 12
import android.net.Uri;
13 13
import android.os.Bundle;
14
import android.os.Environment;
15 14
import android.text.Editable;
16 15
import android.text.Html;
17 16
import android.text.TextUtils;
@ -43,6 +42,7 @@ import com.electric.chargingpile.util.Base64;
43 42
import com.electric.chargingpile.util.CommonParams;
44 43
import com.electric.chargingpile.util.DateUtils;
45 44
import com.electric.chargingpile.util.JsonUtils;
45
import com.electric.chargingpile.util.PhotoUtils;
46 46
import com.electric.chargingpile.util.ToastUtil;
47 47
import com.electric.chargingpile.util.Util;
48 48
import com.luck.picture.lib.PictureSelector;
@ -66,7 +66,7 @@ import java.util.Map;
66 66
67 67
import cn.jpush.android.api.JPushInterface;
68 68
import okhttp3.Call;
69
69
@Deprecated
70 70
public class PublishVideoTopicActivity extends Activity implements OnClickListener {
71 71
    private static final String TAG = "PublishVideoTopicActivity";
72 72
    Context mContext;
@ -85,7 +85,7 @@ public class PublishVideoTopicActivity extends Activity implements OnClickListen
85 85
    private String fileName;
86 86
87 87
88
    public static final String CACHE_DIR = Environment.getExternalStorageDirectory().getAbsolutePath() + "/cdz";
88
    public static final String CACHE_DIR = PhotoUtils.CACHE_DIR;
89 89
90 90
91 91
    public static final String IMAGE_CACHE = CACHE_DIR + "/cache/image/";
@ -241,7 +241,7 @@ public class PublishVideoTopicActivity extends Activity implements OnClickListen
241 241
                        .imageEngine(GlideEngine.createGlideEngine())
242 242
                        .theme(R.style.picture_white_style)// 主题样式设置 具体参考 values/styles   用法:R.style.picture.white.style v2.3.3后 建议使用setPictureStyle()动态方式
243 243
                        .isWeChatStyle(false)// 是否开启微信图片选择风格
244
                        .isUseCustomCamera(true)// 是否使用自定义相机
244
                        .isUseCustomCamera(false)// 是否使用自定义相机
245 245
                        .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
246 246
                        .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
247 247
//                        .setPictureWindowAnimationStyle(mWindowAnimationStyle)// 自定义相册启动退出动画
@ -454,7 +454,7 @@ public class PublishVideoTopicActivity extends Activity implements OnClickListen
454 454
                }
455 455
456 456
                Glide.with(this)
457
                        .load(Uri.fromFile(new File(videoPath)))
457
                        .load(videoPath)
458 458
                        .apply(new RequestOptions().centerCrop())
459 459
                        .into(mItemVideo);
460 460
                mItemVideoLl.setVisibility(View.VISIBLE);

+ 0 - 135
app/src/main/java/com/electric/chargingpile/activity/QRChargingActivity.java

@ -1,135 +0,0 @@
1
package com.electric.chargingpile.activity;
2
3
import android.content.Intent;
4
import android.os.Bundle;
5
import androidx.fragment.app.FragmentActivity;
6
import androidx.viewpager.widget.ViewPager;
7
import android.view.View;
8
import android.widget.ImageView;
9
import android.widget.TextView;
10
11
import com.electric.chargingpile.R;
12
import com.electric.chargingpile.adapter.ViewPagerFragmentAdapter;
13
import com.electric.chargingpile.fragment.AnCiFragment;
14
import com.electric.chargingpile.fragment.YueFragment;
15
import com.electric.chargingpile.util.BarColorUtil;
16
import com.zhy.autolayout.AutoLayout;
17
18
public class QRChargingActivity extends FragmentActivity implements View.OnClickListener {
19
    private ImageView iv_back;
20
    private TextView tv_sure, tv_yue, tv_anci;
21
    private ViewPager viewPager;
22
    private AnCiFragment anCiFragment;
23
    private YueFragment yueFragment;
24
    private ViewPagerFragmentAdapter adapter;
25
    private MyListener listener = new MyListener();
26
27
    @Override
28
    protected void onCreate(Bundle savedInstanceState) {
29
        super.onCreate(savedInstanceState);
30
        AutoLayout.getInstance().auto(this);
31
        setContentView(R.layout.activity_qrcharging);
32
        BarColorUtil.initStatusBarColor(QRChargingActivity.this);
33
34
        initViews();
35
    }
36
37
    private void initViews() {
38
        iv_back = (ImageView) findViewById(R.id.iv_back);
39
        iv_back.setOnClickListener(this);
40
        tv_sure = (TextView) findViewById(R.id.tv_sure);
41
        tv_sure.setOnClickListener(this);
42
        tv_yue = (TextView) findViewById(R.id.tv_yue);
43
        tv_yue.setOnClickListener(this);
44
        tv_anci = (TextView) findViewById(R.id.tv_anci);
45
        tv_anci.setOnClickListener(this);
46
        viewPager = (ViewPager) findViewById(R.id.viewPager);
47
        yueFragment = new YueFragment();
48
        anCiFragment = new AnCiFragment();
49
        adapter = new ViewPagerFragmentAdapter(getSupportFragmentManager());
50
51
        adapter.addFragment(yueFragment);
52
        adapter.addFragment(anCiFragment);
53
54
        viewPager.setOffscreenPageLimit(2);
55
        viewPager.setOnPageChangeListener(listener);
56
        viewPager.setAdapter(adapter);
57
    }
58
59
    @Override
60
    public void onClick(View v) {
61
        switch (v.getId()) {
62
            case R.id.iv_back:
63
                finish();
64
                break;
65
            case R.id.tv_sure:
66
                startActivity(new Intent(getApplication(), ChargingStatusActivity.class));
67
                break;
68
            case R.id.tv_yue:
69
                viewPager.setCurrentItem(0);
70
//                AnCiFragment.cost_way = "";
71
//                AnCiFragment.cost_num = "";
72
//                AnCiFragment.tv_10.setTextColor(getResources().getColor(R.color.ui_65));
73
//                AnCiFragment.tv_20.setTextColor(getResources().getColor(R.color.ui_65));
74
//                AnCiFragment.tv_30.setTextColor(getResources().getColor(R.color.ui_65));
75
//                AnCiFragment.tv_10.setBackgroundResource(R.drawable.bg_huikuang);
76
//                AnCiFragment.tv_20.setBackgroundResource(R.drawable.bg_huikuang);
77
//                AnCiFragment.tv_30.setBackgroundResource(R.drawable.bg_huikuang);
78
//                AnCiFragment.iv_weixin.setImageResource(R.drawable.icon_wugou);
79
//                AnCiFragment.iv_zhifubao.setImageResource(R.drawable.icon_wugou);
80
//                AnCiFragment.et_costnum.setText("");
81
                break;
82
            case R.id.tv_anci:
83
                viewPager.setCurrentItem(1);
84
                break;
85
            default:
86
                break;
87
        }
88
    }
89
90
    public class MyListener implements ViewPager.OnPageChangeListener {
91
92
        @Override
93
        public void onPageScrollStateChanged(int arg0) {
94
95
        }
96
97
        @Override
98
        public void onPageScrolled(int position, float positionOffset,
99
                                   int positionOffsetPixels) {
100
//            resetViewPagerHeight(position);
101
        }
102
103
        @Override
104
        public void onPageSelected(int position) {
105
            // 页面切换后重置ViewPager高度
106
//            resetViewPagerHeight(position);
107
            setBackground(position);
108
        }
109
    }
110
111
    private void setBackground(int left) {
112
        if (left == 0) {
113
            tv_yue.setBackgroundResource(R.drawable.bg_lv);
114
            tv_anci.setBackgroundResource(R.drawable.bg_hui);
115
            tv_yue.setTextColor(getResources().getColor(R.color.lvse));
116
            tv_anci.setTextColor(getResources().getColor(R.color.ui_62));
117
        } else if (left == 1) {
118
            tv_anci.setBackgroundResource(R.drawable.bg_lv);
119
            tv_yue.setBackgroundResource(R.drawable.bg_hui);
120
            tv_yue.setTextColor(getResources().getColor(R.color.ui_62));
121
            tv_anci.setTextColor(getResources().getColor(R.color.lvse));
122
        }
123
124
    }
125
126
    @Override
127
    protected void onResume() {
128
        super.onResume();
129
    }
130
131
    @Override
132
    protected void onPause() {
133
        super.onPause();
134
    }
135
}

+ 31 - 10
app/src/main/java/com/electric/chargingpile/activity/RoutePlanMapActivity.java

@ -2,6 +2,8 @@ package com.electric.chargingpile.activity;
2 2
3 3
import android.animation.ValueAnimator;
4 4
import android.app.Activity;
5
import android.content.ContentResolver;
6
import android.content.ContentValues;
5 7
import android.content.Context;
6 8
import android.content.DialogInterface;
7 9
import android.content.Intent;
@ -18,8 +20,8 @@ import android.graphics.Matrix;
18 20
import android.graphics.drawable.BitmapDrawable;
19 21
import android.graphics.drawable.Drawable;
20 22
import android.net.Uri;
23
import android.os.Build;
21 24
import android.os.Bundle;
22
import android.os.Environment;
23 25
import android.os.Handler;
24 26
import android.provider.MediaStore;
25 27
@ -51,7 +53,7 @@ import com.amap.api.maps.AMapUtils;
51 53
import com.amap.api.maps.CameraUpdateFactory;
52 54
import com.amap.api.maps.LocationSource;
53 55
import com.amap.api.maps.MapView;
54
import com.amap.api.maps.UiSettings;
56
55 57
import com.amap.api.maps.model.BitmapDescriptorFactory;
56 58
import com.amap.api.maps.model.CameraPosition;
57 59
import com.amap.api.maps.model.LatLng;
@ -109,6 +111,7 @@ import com.electric.chargingpile.util.DES3S;
109 111
import com.electric.chargingpile.util.DensityUtil;
110 112
import com.electric.chargingpile.util.JsonUtils;
111 113
import com.electric.chargingpile.util.LoadingDialog;
114
import com.electric.chargingpile.util.PhotoUtils;
112 115
import com.electric.chargingpile.util.ToastUtil;
113 116
import com.electric.chargingpile.util.Util;
114 117
import com.electric.chargingpile.view.MyAutoLayout;
@ -127,6 +130,7 @@ import java.io.File;
127 130
import java.io.FileNotFoundException;
128 131
import java.io.FileOutputStream;
129 132
import java.io.IOException;
133
import java.io.OutputStream;
130 134
import java.net.URLEncoder;
131 135
import java.text.SimpleDateFormat;
132 136
import java.util.ArrayList;
@ -2578,7 +2582,7 @@ public class RoutePlanMapActivity extends Activity implements LocationSource, AM
2578 2582
                    return;
2579 2583
                }
2580 2584
                try {
2581
                    FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory() + "/test_" + sdf.format(new Date()) + ".png");
2585
                    FileOutputStream fos = new FileOutputStream(PhotoUtils.CACHE_DIR + "/test_" + sdf.format(new Date()) + ".png");
2582 2586
                    try {
2583 2587
                        fos.flush();
2584 2588
                    } catch (IOException e) {
@ -2605,7 +2609,7 @@ public class RoutePlanMapActivity extends Activity implements LocationSource, AM
2605 2609
        paramsToShare.setTitle(null);
2606 2610
        paramsToShare.setTitleUrl(null);
2607 2611
        paramsToShare.setUrl("http://a.app.qq.com/o/simple.jsp?pkgname=com.electric.chargingpile");
2608
        paramsToShare.setImagePath(Environment.getExternalStorageDirectory() + File.separator + "d1ev/share.png");
2612
        paramsToShare.setImagePath(PhotoUtils.CACHE_DIR + File.separator + "d1ev/share.png");
2609 2613
        paramsToShare.setShareType(Platform.SHARE_IMAGE);
2610 2614
        Platform platform = ShareSDK.getPlatform(name);
2611 2615
        platform.setPlatformActionListener(new PlatformActionListener() {
@ -2738,8 +2742,9 @@ public class RoutePlanMapActivity extends Activity implements LocationSource, AM
2738 2742
    }
2739 2743
2740 2744
    public void saveBitmap(Bitmap mBitmap) {
2745
2741 2746
        LogUtils.e(mBitmap.getByteCount());
2742
        String dir_path = Environment.getExternalStorageDirectory() + File.separator + "d1ev/";
2747
        String dir_path = PhotoUtils.CACHE_DIR+ "d1ev/";
2743 2748
        File directory = new File(dir_path);
2744 2749
        File f = new File(directory, "share.png");
2745 2750
        try {
@ -2767,11 +2772,27 @@ public class RoutePlanMapActivity extends Activity implements LocationSource, AM
2767 2772
        } catch (IOException e) {
2768 2773
            e.printStackTrace();
2769 2774
        }
2770
        MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");
2771
        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
2772
        Uri uri = Uri.fromFile(new File(dir_path));
2773
        intent.setData(uri);
2774
        getApplicationContext().sendBroadcast(intent);
2775
2776
        ContentResolver contentResolver = MainApplication.context.getContentResolver();
2777
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
2778
            Uri insert = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
2779
            try {
2780
                OutputStream outputStream =  contentResolver.openOutputStream(insert);
2781
                if (outputStream!=null){
2782
                    mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
2783
                }
2784
            } catch (FileNotFoundException e) {
2785
                e.printStackTrace();
2786
            }
2787
2788
        }else{
2789
            MediaStore.Images.Media.insertImage(contentResolver, mBitmap, "", "");
2790
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
2791
            Uri uri = PhotoUtils.parseUri(new File(dir_path));
2792
            intent.setData(uri);
2793
            getApplicationContext().sendBroadcast(intent);
2794
        }
2795
2775 2796
    }
2776 2797
2777 2798

+ 58 - 160
app/src/main/java/com/electric/chargingpile/activity/ShareTwoActivity.java

@ -12,19 +12,11 @@ import android.graphics.Bitmap;
12 12
import android.graphics.BitmapFactory;
13 13
import android.graphics.Color;
14 14
import android.graphics.Matrix;
15
import android.graphics.drawable.BitmapDrawable;
16 15
import android.graphics.drawable.ColorDrawable;
17
import android.net.Uri;
16
import android.os.Build;
18 17
import android.os.Bundle;
19
import android.os.Environment;
20 18
import android.os.Handler;
21 19
import android.os.Message;
22
import android.provider.MediaStore;
23
24
import androidx.annotation.NonNull;
25
import androidx.constraintlayout.widget.ConstraintLayout;
26
import androidx.core.content.FileProvider;
27
28 20
import android.util.Base64;
29 21
import android.util.Log;
30 22
import android.view.KeyEvent;
@ -49,18 +41,20 @@ import android.widget.TimePicker;
49 41
import android.widget.Toast;
50 42
import android.widget.ToggleButton;
51 43
44
import androidx.annotation.NonNull;
45
import androidx.constraintlayout.widget.ConstraintLayout;
46
52 47
import com.electric.chargingpile.R;
53 48
import com.electric.chargingpile.application.MainApplication;
54 49
import com.electric.chargingpile.data.OperatorData;
55 50
import com.electric.chargingpile.data.Zhan;
51
import com.electric.chargingpile.engine.GlideEngine;
56 52
import com.electric.chargingpile.manager.ProfileManager;
57 53
import com.electric.chargingpile.util.BarColorUtil;
58 54
import com.electric.chargingpile.util.Bimp;
59 55
import com.electric.chargingpile.util.DES3;
60 56
import com.electric.chargingpile.util.DensityUtil;
61
import com.electric.chargingpile.util.FileUtils;
62 57
import com.electric.chargingpile.util.ImageItem;
63
import com.electric.chargingpile.util.ImageUtils;
64 58
import com.electric.chargingpile.util.JsonUtils;
65 59
import com.electric.chargingpile.util.OkHttpUtil;
66 60
import com.electric.chargingpile.util.PublicWayFour;
@ -68,16 +62,18 @@ import com.electric.chargingpile.util.Res;
68 62
import com.electric.chargingpile.util.SharedPreferencesUtil;
69 63
import com.electric.chargingpile.util.ToastUtil;
70 64
import com.electric.chargingpile.util.UploadUtil;
65
import com.electric.chargingpile.util.Util;
71 66
import com.electric.chargingpile.view.CustomProgressDialog;
72 67
import com.electric.chargingpile.view.ShareDialog;
73 68
import com.google.gson.Gson;
74 69
import com.google.gson.reflect.TypeToken;
70
import com.luck.picture.lib.PictureSelector;
71
import com.luck.picture.lib.animators.AnimationType;
72
import com.luck.picture.lib.config.PictureConfig;
73
import com.luck.picture.lib.config.PictureMimeType;
74
import com.luck.picture.lib.entity.LocalMedia;
75 75
import com.squareup.okhttp.Request;
76 76
import com.squareup.okhttp.Response;
77
import com.zhihu.matisse.Matisse;
78
import com.zhihu.matisse.MimeType;
79
import com.zhihu.matisse.engine.impl.GlideEngine;
80
import com.zhihu.matisse.internal.entity.CaptureStrategy;
81 77
import com.zhy.http.okhttp.OkHttpUtils;
82 78
import com.zhy.http.okhttp.callback.StringCallback;
83 79
@ -86,7 +82,6 @@ import org.json.JSONObject;
86 82
87 83
import java.io.ByteArrayInputStream;
88 84
import java.io.ByteArrayOutputStream;
89
import java.io.File;
90 85
import java.io.IOException;
91 86
import java.text.DecimalFormat;
92 87
import java.util.ArrayList;
@ -118,9 +113,8 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
118 113
    private TimePickerDialog tpd_close = null;
119 114
    private String camePath;//拍照路径
120 115
121
    private static final String PHOTO_FILE_NAME = "android.jpg";
122
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
123
    private File tempFile;
116
117
124 118
    private static final int PHOTO_REQUEST_CAMERA = 1;
125 119
    private static final int PHOTO_REQUEST_GALLERY = 2;
126 120
    private static final int PHOTO_REQUEST_CUT = 3;
@ -169,8 +163,7 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
169 163
    private GridView noScrollgridview;
170 164
    private GridAdapter adapter;
171 165
    private View parentView;
172
    private PopupWindow pop = null;
173
    private LinearLayout ll_popup;
166
174 167
    private TextView open_time, close_time, share_list;
175 168
    private RelativeLayout rl_address;
176 169
    private ProgressDialog insertDialog;
@ -265,7 +258,6 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
265 258
    @Override
266 259
    protected void onCreate(Bundle savedInstanceState) {
267 260
        super.onCreate(savedInstanceState);
268
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
269 261
        Res.init(this);
270 262
        bimap = BitmapFactory.decodeResource(
271 263
                getResources(),
@ -323,65 +315,6 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
323 315
        selectBitmap[2] = null;
324 316
        selectBitmap[3] = null;
325 317
326
        pop = new PopupWindow(ShareTwoActivity.this);
327
328
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
329
330
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
331
332
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
333
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
334
        pop.setBackgroundDrawable(new BitmapDrawable());
335
        pop.setFocusable(true);
336
        pop.setOutsideTouchable(true);
337
        pop.setContentView(view);
338
339
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
340
        Button bt1 = (Button) view
341
                .findViewById(R.id.item_popupwindows_camera);
342
        Button bt2 = (Button) view
343
                .findViewById(R.id.item_popupwindows_Photo);
344
        Button bt3 = (Button) view
345
                .findViewById(R.id.item_popupwindows_cancel);
346
        parent.setOnClickListener(new View.OnClickListener() {
347
348
            @Override
349
            public void onClick(View v) {
350
                // TODO Auto-generated method stub
351
                pop.dismiss();
352
                ll_popup.clearAnimation();
353
            }
354
        });
355
        bt1.setOnClickListener(new View.OnClickListener() {
356
            public void onClick(View v) {
357
                pop.dismiss();
358
                ll_popup.clearAnimation();
359
360
                if (MainScanActivity.isCameraUseable()) {
361
                    photo();
362
                } else {
363
                    ToastUtil.showToast(getApplicationContext(), "您当前关闭了调用摄像头权限,可前往设置开启权限", Toast.LENGTH_SHORT);
364
                }
365
366
            }
367
        });
368
        bt2.setOnClickListener(new View.OnClickListener() {
369
            public void onClick(View v) {
370
                Intent intent = new Intent(ShareTwoActivity.this,
371
                        AlbumActivity.class);
372
                startActivity(intent);
373
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
374
//                startActivityForResult(intent, 1);
375
                pop.dismiss();
376
                ll_popup.clearAnimation();
377
            }
378
        });
379
        bt3.setOnClickListener(new View.OnClickListener() {
380
            public void onClick(View v) {
381
                pop.dismiss();
382
                ll_popup.clearAnimation();
383
            }
384
        });
385 318
386 319
        noScrollgridview = (GridView) findViewById(R.id.noScrollgridview);
387 320
        noScrollgridview.setSelector(new ColorDrawable(Color.TRANSPARENT));
@ -411,6 +344,7 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
411 344
     * 调用图库选择
412 345
     */
413 346
    private void callGallery() {
347
/*
414 348
        Matisse.from(ShareTwoActivity.this)
415 349
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
416 350
                .showSingleMediaType(true)
@ -420,6 +354,26 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
420 354
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
421 355
                .imageEngine(new GlideEngine())
422 356
                .forResult(REQUEST_CODE_CHOOSE);
357
*/
358
        PictureSelector.create(this)
359
                .openGallery(PictureMimeType.ofImage())
360
                .selectionMode(PictureConfig.SINGLE)
361
                .isCompress(true)//是否压缩
362
                .isSingleDirectReturn(true)
363
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
364
                .isGif(true)//是否显示gif
365
                .isAndroidQTransform(true)
366
                .imageEngine(GlideEngine.createGlideEngine())
367
                .isWeChatStyle(false)// 是否开启微信图片选择风格
368
                .isUseCustomCamera(false)// 是否使用自定义相机
369
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
370
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
371
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
372
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
373
                .imageSpanCount(4)// 每行显示个数
374
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
375
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
376
                .forResult(REQUEST_CODE_CHOOSE);
423 377
    }
424 378
425 379
    @Override
@ -449,20 +403,30 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
449 403
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
450 404
451 405
                try {
452
                    List<Uri> uriList = Matisse.obtainResult(data);
453
                    Uri uri = uriList.get(0);
454
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
455
                    File file = FileUtils.from(ShareTwoActivity.this, uri);
456
457
                    bitmap = FileUtils.rotateIfRequired(file, bitmap);
458
                    bitmap = imageZoom(bitmap);
406
                    List<LocalMedia> mediaList = PictureSelector.obtainMultipleResult(data);
407
                    if (mediaList!=null && mediaList.size()>0){
408
                       /* List<Uri> uriList = Matisse.obtainResult(data);
409
                        Uri uri = uriList.get(0);
410
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
411
                        File file = FileUtils.from(ShareTwoActivity.this, uri);
412
413
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
414
                        bitmap = imageZoom(bitmap);
415
*/
416
                        String path="";
417
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
418
                            path= mediaList.get(0).getAndroidQToPath();
419
                        }else{
420
                            path=mediaList.get(0).getPath();
421
                        }
422
                        ImageItem takePhoto = new ImageItem();
423
                        takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
424
                        selectBitmap[selectIndex] = takePhoto;
459 425
460
                    ImageItem takePhoto = new ImageItem();
461
                    takePhoto.setBitmap(bitmap);
462
                    selectBitmap[selectIndex] = takePhoto;
426
                        subscriber.onNext("");
427
                        subscriber.onComplete();
428
                    }
463 429
464
                    subscriber.onNext("");
465
                    subscriber.onComplete();
466 430
                } catch (Exception e) {
467 431
                    e.printStackTrace();
468 432
                    subscriber.onError(e);
@ -1156,15 +1120,6 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
1156 1120
1157 1121
    private static final int TAKE_PICTURE = 0x000001;
1158 1122
1159
    public void photo() {
1160
        if (hasSdcard()) {
1161
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1162
            Uri photoURI = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", tempFile);
1163
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
1164
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
1165
        }
1166
    }
1167
1168 1123
1169 1124
    @Override
1170 1125
    protected void onDestroy() {
@ -1172,64 +1127,7 @@ public class ShareTwoActivity extends Activity implements View.OnClickListener,
1172 1127
        Bimp.max = 0;
1173 1128
        super.onDestroy();
1174 1129
    }
1175
1176
1177
    private Bitmap compressBmpFromBmp(Bitmap image) {
1178
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1179
        int options = 100;
1180
        image.compress(Bitmap.CompressFormat.JPEG, 60, baos);
1181
        while (baos.toByteArray().length / 1024 > 200) {
1182
            baos.reset();
1183
            options -= 10;
1184
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);
1185
        }
1186
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
1187
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
1188
        return bitmap;
1189
    }
1190
1191
1192
    private void crop(Uri uri, Uri cutImgUri) {
1193
        Intent intent = new Intent("com.android.camera.action.CROP");
1194
        intent.setDataAndType(uri, "image/*");
1195
        intent.putExtra("crop", "true");
1196
        intent.putExtra("outputFormat", "JPEG");
1197
        intent.putExtra("noFaceDetection", true);
1198
        intent.putExtra("return-data", false);
1199
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cutImgUri);
1200
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
1201
    }
1202
1203
    private boolean hasSdcard() {
1204
        if (Environment.getExternalStorageState().equals(
1205
                Environment.MEDIA_MOUNTED)) {
1206
            return true;
1207
        } else {
1208
            return false;
1209
        }
1210
    }
1211
1212
    private static String getPath(String path) {
1213
        File f = new File(path);
1214
        if (!f.exists()) {
1215
            f.mkdirs();
1216
        }
1217
        return f.getAbsolutePath();
1218
    }
1219
1220
    private File getFile(String path) {
1221
        File f = new File(path);
1222
        if (!f.exists()) {
1223
            try {
1224
                f.createNewFile();
1225
            } catch (IOException e) {
1226
                e.printStackTrace();
1227
            }
1228
        }
1229
        return f;
1230
    }
1231
1232
1130
    
1233 1131
    private Bitmap compressImage(Bitmap image) {
1234 1132
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1235 1133
        image.compress(Bitmap.CompressFormat.JPEG, 80, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中

+ 63 - 133
app/src/main/java/com/electric/chargingpile/activity/ShareTwoEditActivity.java

@ -13,17 +13,11 @@ import android.graphics.Matrix;
13 13
import android.graphics.drawable.BitmapDrawable;
14 14
import android.graphics.drawable.Drawable;
15 15
import android.net.Uri;
16
import android.os.Build;
16 17
import android.os.Bundle;
17
import android.os.Environment;
18 18
import android.os.Handler;
19 19
import android.os.Message;
20 20
import android.provider.MediaStore;
21
22
import androidx.annotation.NonNull;
23
import androidx.annotation.Nullable;
24
import androidx.constraintlayout.widget.ConstraintLayout;
25
import androidx.core.content.FileProvider;
26
27 21
import android.util.Base64;
28 22
import android.util.Log;
29 23
import android.view.KeyEvent;
@ -33,7 +27,6 @@ import android.widget.Button;
33 27
import android.widget.EditText;
34 28
import android.widget.ImageView;
35 29
import android.widget.LinearLayout;
36
import android.widget.PopupWindow;
37 30
import android.widget.RadioButton;
38 31
import android.widget.RadioGroup;
39 32
import android.widget.RelativeLayout;
@ -43,6 +36,10 @@ import android.widget.TimePicker;
43 36
import android.widget.Toast;
44 37
import android.widget.ToggleButton;
45 38
39
import androidx.annotation.NonNull;
40
import androidx.annotation.Nullable;
41
import androidx.constraintlayout.widget.ConstraintLayout;
42
46 43
import com.bumptech.glide.Glide;
47 44
import com.bumptech.glide.load.DataSource;
48 45
import com.bumptech.glide.load.engine.GlideException;
@ -50,15 +47,12 @@ import com.bumptech.glide.request.RequestListener;
50 47
import com.bumptech.glide.request.target.Target;
51 48
import com.electric.chargingpile.R;
52 49
import com.electric.chargingpile.application.MainApplication;
53
import com.electric.chargingpile.data.OperatorData;
54 50
import com.electric.chargingpile.data.Zhan;
55
import com.electric.chargingpile.manager.ProfileManager;
51
import com.electric.chargingpile.engine.GlideEngine;
56 52
import com.electric.chargingpile.util.BarColorUtil;
57 53
import com.electric.chargingpile.util.DES3;
58 54
import com.electric.chargingpile.util.DensityUtil;
59
import com.electric.chargingpile.util.FileUtils;
60 55
import com.electric.chargingpile.util.ImageItem;
61
import com.electric.chargingpile.util.ImageUtils;
62 56
import com.electric.chargingpile.util.JsonUtils;
63 57
import com.electric.chargingpile.util.OkHttpUtil;
64 58
import com.electric.chargingpile.util.PublicWayFour;
@ -66,17 +60,17 @@ import com.electric.chargingpile.util.Res;
66 60
import com.electric.chargingpile.util.SharedPreferencesUtil;
67 61
import com.electric.chargingpile.util.ToastUtil;
68 62
import com.electric.chargingpile.util.UploadUtil;
63
import com.electric.chargingpile.util.Util;
69 64
import com.electric.chargingpile.view.CustomProgressDialog;
70 65
import com.electric.chargingpile.view.ShareDialog;
71
import com.google.gson.Gson;
72
import com.google.gson.reflect.TypeToken;
66
import com.luck.picture.lib.PictureSelector;
67
import com.luck.picture.lib.animators.AnimationType;
68
import com.luck.picture.lib.config.PictureConfig;
69
import com.luck.picture.lib.config.PictureMimeType;
70
import com.luck.picture.lib.entity.LocalMedia;
73 71
import com.squareup.okhttp.Request;
74 72
import com.squareup.okhttp.Response;
75 73
import com.tencent.bugly.crashreport.CrashReport;
76
import com.zhihu.matisse.Matisse;
77
import com.zhihu.matisse.MimeType;
78
import com.zhihu.matisse.engine.impl.GlideEngine;
79
import com.zhihu.matisse.internal.entity.CaptureStrategy;
80 74
import com.zhy.http.okhttp.OkHttpUtils;
81 75
import com.zhy.http.okhttp.callback.StringCallback;
82 76
@ -86,7 +80,6 @@ import org.json.JSONObject;
86 80
87 81
import java.io.ByteArrayInputStream;
88 82
import java.io.ByteArrayOutputStream;
89
import java.io.File;
90 83
import java.io.IOException;
91 84
import java.net.URLEncoder;
92 85
import java.text.DecimalFormat;
@ -119,9 +112,7 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
119 112
    private TimePickerDialog tpd_close = null;
120 113
    private String camePath;//拍照路径
121 114
122
    private static final String PHOTO_FILE_NAME = "android.jpg";
123
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
124
    private File tempFile;
115
125 116
    private static final int PHOTO_REQUEST_CAMERA = 1;
126 117
    private static final int PHOTO_REQUEST_GALLERY = 2;
127 118
    private static final int PHOTO_REQUEST_CUT = 3;
@ -156,8 +147,7 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
156 147
    private RadioGroup rg_claimtype, rg_park;
157 148
    public static Bitmap bimap;
158 149
    private View parentView;
159
    private PopupWindow pop = null;
160
    private LinearLayout ll_popup;
150
161 151
    private TextView open_time, close_time;
162 152
    private RelativeLayout rl_address;
163 153
    private ProgressDialog insertDialog;
@ -252,7 +242,7 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
252 242
    @Override
253 243
    protected void onCreate(Bundle savedInstanceState) {
254 244
        super.onCreate(savedInstanceState);
255
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
245
256 246
        Res.init(this);
257 247
        bimap = BitmapFactory.decodeResource(
258 248
                getResources(),
@ -303,70 +293,13 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
303 293
        selectBitmap[2] = null;
304 294
        selectBitmap[3] = null;
305 295
306
        pop = new PopupWindow(ShareTwoEditActivity.this);
307
308
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
309
310
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
311
312
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
313
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
314
        pop.setBackgroundDrawable(new BitmapDrawable());
315
        pop.setFocusable(true);
316
        pop.setOutsideTouchable(true);
317
        pop.setContentView(view);
318
319
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
320
        Button bt1 = (Button) view
321
                .findViewById(R.id.item_popupwindows_camera);
322
        Button bt2 = (Button) view
323
                .findViewById(R.id.item_popupwindows_Photo);
324
        Button bt3 = (Button) view
325
                .findViewById(R.id.item_popupwindows_cancel);
326
        parent.setOnClickListener(new View.OnClickListener() {
327
328
            @Override
329
            public void onClick(View v) {
330
                // TODO Auto-generated method stub
331
                pop.dismiss();
332
                ll_popup.clearAnimation();
333
            }
334
        });
335
        bt1.setOnClickListener(new View.OnClickListener() {
336
            public void onClick(View v) {
337
                pop.dismiss();
338
                ll_popup.clearAnimation();
339
340
                if (MainScanActivity.isCameraUseable()) {
341
                    photo();
342
                } else {
343
                    ToastUtil.showToast(getApplicationContext(), "您当前关闭了调用摄像头权限,可前往设置开启权限", Toast.LENGTH_SHORT);
344
                }
345
346
            }
347
        });
348
        bt2.setOnClickListener(new View.OnClickListener() {
349
            public void onClick(View v) {
350
                Intent intent = new Intent(ShareTwoEditActivity.this,
351
                        AlbumActivity.class);
352
                startActivity(intent);
353
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
354
                pop.dismiss();
355
                ll_popup.clearAnimation();
356
            }
357
        });
358
        bt3.setOnClickListener(new View.OnClickListener() {
359
            public void onClick(View v) {
360
                pop.dismiss();
361
                ll_popup.clearAnimation();
362
            }
363
        });
364 296
    }
365 297
366 298
    /**
367 299
     * 调用图库选择
368 300
     */
369 301
    private void callGallery() {
302
/*
370 303
        Matisse.from(ShareTwoEditActivity.this)
371 304
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
372 305
                .showSingleMediaType(true)
@ -376,6 +309,27 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
376 309
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
377 310
                .imageEngine(new GlideEngine())
378 311
                .forResult(REQUEST_CODE_CHOOSE);
312
*/
313
        PictureSelector.create(this)
314
                .openGallery(PictureMimeType.ofImage())
315
                .selectionMode(PictureConfig.SINGLE)
316
                .isSingleDirectReturn(true)
317
                .isCompress(true)//是否压缩
318
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
319
                .isGif(true)//是否显示gif
320
                .isAndroidQTransform(true)
321
                .imageEngine(GlideEngine.createGlideEngine())
322
                .isWeChatStyle(false)// 是否开启微信图片选择风格
323
                .isUseCustomCamera(false)// 是否使用自定义相机
324
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
325
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
326
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
327
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
328
                .imageSpanCount(4)// 每行显示个数
329
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
330
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
331
                .forResult(REQUEST_CODE_CHOOSE);
332
379 333
    }
380 334
381 335
    @Override
@ -404,21 +358,33 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
404 358
            @Override
405 359
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
406 360
                try {
407
                    List<Uri> uriList = Matisse.obtainResult(data);
408
                    Uri uri = uriList.get(0);
409
                    Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
410
                    File file = FileUtils.from(ShareTwoEditActivity.this, uri);
411
412
                    bitmap = FileUtils.rotateIfRequired(file, bitmap);
413
                    bitmap = imageZoom(bitmap);
414
415
                    ImageItem takePhoto = new ImageItem();
416
                    takePhoto.setBitmap(bitmap);
417
                    selectBitmap[selectIndex] = takePhoto;
418
                    isTakePhoto = true;
361
                    List<LocalMedia> mediaList = PictureSelector.obtainMultipleResult(data);
362
                    if (mediaList!=null && mediaList.size()>0){
363
                      /*  List<Uri> uriList = Matisse.obtainResult(data);
364
                        Uri uri = uriList.get(0);
365
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
366
                        File file = FileUtils.from(ShareTwoEditActivity.this, uri);
367
368
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
369
                        bitmap = imageZoom(bitmap);
370
*/
371
                        String path="";
372
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
373
                            path= mediaList.get(0).getAndroidQToPath();
374
                        }else{
375
                            path=mediaList.get(0).getPath();
376
                        }
377
                        ImageItem takePhoto = new ImageItem();
378
                        takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
379
                        selectBitmap[selectIndex] = takePhoto;
380
                        isTakePhoto = true;
381
382
                        subscriber.onNext("");
383
                        subscriber.onComplete();
384
                    }else{
385
                        subscriber.onError(new Exception(""));
386
                    }
419 387
420
                    subscriber.onNext("");
421
                    subscriber.onComplete();
422 388
                } catch (Exception e) {
423 389
                    e.printStackTrace();
424 390
                    subscriber.onError(e);
@ -1016,15 +982,6 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
1016 982
1017 983
    private static final int TAKE_PICTURE = 0x000001;
1018 984
1019
    public void photo() {
1020
        if (hasSdcard()) {
1021
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
1022
            Uri photoURI = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", tempFile);
1023
            intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
1024
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
1025
        }
1026
    }
1027
1028 985
1029 986
    @Override
1030 987
    protected void onDestroy() {
@ -1058,34 +1015,7 @@ public class ShareTwoEditActivity extends Activity implements View.OnClickListen
1058 1015
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
1059 1016
    }
1060 1017
1061
    private boolean hasSdcard() {
1062
        if (Environment.getExternalStorageState().equals(
1063
                Environment.MEDIA_MOUNTED)) {
1064
            return true;
1065
        } else {
1066
            return false;
1067
        }
1068
    }
1069
1070
    private static String getPath(String path) {
1071
        File f = new File(path);
1072
        if (!f.exists()) {
1073
            f.mkdirs();
1074
        }
1075
        return f.getAbsolutePath();
1076
    }
1077 1018
1078
    private File getFile(String path) {
1079
        File f = new File(path);
1080
        if (!f.exists()) {
1081
            try {
1082
                f.createNewFile();
1083
            } catch (IOException e) {
1084
                e.printStackTrace();
1085
            }
1086
        }
1087
        return f;
1088
    }
1089 1019
1090 1020
1091 1021
    private Bitmap compressImage(Bitmap image) {

+ 96 - 45
app/src/main/java/com/electric/chargingpile/activity/SkipUserInfoActivity.java

@ -45,6 +45,7 @@ import com.electric.chargingpile.application.MainApplication;
45 45
import com.electric.chargingpile.data.CarOwnerCertificateBean;
46 46
import com.electric.chargingpile.data.Cars;
47 47
import com.electric.chargingpile.data.Province;
48
import com.electric.chargingpile.engine.GlideEngine;
48 49
import com.electric.chargingpile.entity.CarModelEntity;
49 50
import com.electric.chargingpile.entity.CarSeriesEntity;
50 51
import com.electric.chargingpile.event.CarIntentModelEvent;
@ -62,12 +63,19 @@ import com.electric.chargingpile.util.PhotoUtils;
62 63
import com.electric.chargingpile.util.StatusConstants;
63 64
import com.electric.chargingpile.util.ToastUtil;
64 65
import com.electric.chargingpile.util.UploadUtil;
66
import com.electric.chargingpile.util.Util;
65 67
import com.electric.chargingpile.view.CustomProgressDialog;
66 68
import com.electric.chargingpile.view.RoundImageView;
67 69
import com.electric.chargingpile.view.xrichtext.SDCardUtil;
68 70
import com.google.gson.Gson;
71
import com.luck.picture.lib.PictureSelector;
72
import com.luck.picture.lib.animators.AnimationType;
73
import com.luck.picture.lib.config.PictureConfig;
74
import com.luck.picture.lib.config.PictureMimeType;
75
import com.luck.picture.lib.entity.LocalMedia;
69 76
import com.squareup.okhttp.Request;
70 77
import com.squareup.okhttp.Response;
78
import com.yalantis.ucrop.view.OverlayView;
71 79
import com.zhy.http.okhttp.OkHttpUtils;
72 80
import com.zhy.http.okhttp.callback.StringCallback;
73 81
@ -81,6 +89,7 @@ import org.json.JSONObject;
81 89
82 90
import java.io.ByteArrayOutputStream;
83 91
import java.io.File;
92
import java.io.FileOutputStream;
84 93
import java.io.IOException;
85 94
import java.net.URLEncoder;
86 95
import java.util.ArrayList;
@ -129,10 +138,7 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
129 138
    private TextView tv_point;
130 139
    private RelativeLayout rl_point;
131 140
    private Bitmap download_bmp;
132
    private File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/photo.jpg");
133
    private File fileCropUri = new File(Environment.getExternalStorageDirectory().getPath() + "/crop_photo.jpg");
134
    private Uri imageUri;
135
    private Uri cropImageUri;
141
136 142
    private static final int RC_CAMERA_PERM = 123;
137 143
    private SkipUserInfoActivity activity;
138 144
@ -355,11 +361,7 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
355 361
        btn_two.setOnClickListener(new View.OnClickListener() {
356 362
            @Override
357 363
            public void onClick(View view) {
358
                Intent intent = new Intent(Intent.ACTION_PICK, null);
359
                intent.setDataAndType(
360
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
361
                        "image/*");
362
                startActivityForResult(intent, 1);
364
                openPhotoAlbum();
363 365
                popupWindow.dismiss();
364 366
            }
365 367
        });
@ -466,7 +468,9 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
466 468
            case R.id.iv_right:
467 469
//                startActivity(new Intent(SkipUserInfoActivity.this,LoginActivity.class));
468 470
                Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon_user1118);
469
                ImageTools.saveImageToGallery(getApplicationContext(), bmp, "user_icon");
471
//                ImageTools.saveImageToGallery(getApplicationContext(), bmp, "user_icon.jpg");
472
                String storePath = PhotoUtils.CACHE_DIR + File.separator + "cdz_android";
473
                PhotoUtils.saveBitmap(this,bmp,storePath,"user_icon.jpeg");
470 474
                ProfileManager.getInstance().setFirstPoint(SkipUserInfoActivity.this, "1");
471 475
                ActivityManagerApplication.destoryActivity("login");
472 476
                CreditActivity.canFresh = true;
@ -485,7 +489,7 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
485 489
                            shite("");
486 490
                        }
487 491
                    }).start();
488
                    if (mCarModelEntity!=null){
492
                    if (mCarModelEntity != null) {
489 493
                        requestCarIntentModel();
490 494
                    }
491 495
                    createDialog();
@ -510,16 +514,67 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
510 514
     * @param view
511 515
     */
512 516
    public void takePhoto(View view) {
513
        if (SDCardUtil.hasSdcard()) {
514
            imageUri = Uri.fromFile(fileUri);
515
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
516
                //通过FileProvider创建一个content类型的Uri
517
                imageUri = FileProvider.getUriForFile(SkipUserInfoActivity.this, "com.electric.chargingpile.provider", fileUri);
518
            PhotoUtils.takePicture(SkipUserInfoActivity.this, imageUri, 2);
519
        } else {
520
            Toast.makeText(SkipUserInfoActivity.this, "设备没有SD卡!", Toast.LENGTH_SHORT).show();
521
            Log.e("asd", "设备没有SD卡");
522
        }
517
        PictureSelector.create(this)
518
                .openCamera(PictureMimeType.ofImage())
519
                .selectionMode(PictureConfig.SINGLE)
520
                .isSingleDirectReturn(true)
521
                .isCompress(true)//是否压缩
522
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
523
                .isGif(false)//是否显示gif
524
                .isAndroidQTransform(true)
525
                .imageEngine(GlideEngine.createGlideEngine())
526
                .isWeChatStyle(false)// 是否开启微信图片选择风格
527
                .isUseCustomCamera(false)// 是否使用自定义相机
528
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
529
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
530
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
531
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
532
                .imageSpanCount(4)// 每行显示个数
533
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
534
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
535
                .isEnableCrop(true)
536
                .rotateEnabled(false)//裁剪是否可旋转图片
537
                .setCircleStrokeWidth(8)//设置圆形裁剪边框粗细
538
                .freeStyleCropMode(OverlayView.DEFAULT_FREESTYLE_CROP_MODE)// 裁剪框拖动模式
539
                .isCropDragSmoothToCenter(true)// 裁剪框拖动时图片自动跟随居中
540
                .circleDimmedLayer(true)// 是否开启圆形裁剪
541
                .isDragFrame(true)//是否可拖动裁剪框(固定)
542
                .showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
543
                .showCropGrid(false)//是否显示裁剪矩形网格 圆形裁剪时建议设为false
544
                .forResult(2);
545
546
    }
547
    private void openPhotoAlbum() {
548
        PictureSelector.create(this)
549
                .openGallery(PictureMimeType.ofImage())
550
                .isCamera(false)//列表是否显示拍照按钮
551
                .selectionMode(PictureConfig.SINGLE)
552
                .isSingleDirectReturn(true)//PictureConfig.SINGLE模式下是否直接返回
553
                .isCompress(true)//是否压缩
554
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
555
                .isGif(false)//是否显示gif
556
                .isAndroidQTransform(true)
557
                .imageEngine(GlideEngine.createGlideEngine())
558
                .isWeChatStyle(false)// 是否开启微信图片选择风格
559
                .isUseCustomCamera(false)// 是否使用自定义相机
560
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
561
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
562
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
563
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
564
                .imageSpanCount(4)// 每行显示个数
565
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
566
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
567
                .rotateEnabled(false)//裁剪是否可旋转图片
568
                .isEnableCrop(true)
569
                .rotateEnabled(false)//裁剪是否可旋转图片
570
                .setCircleStrokeWidth(8)//设置圆形裁剪边框粗细
571
                .freeStyleCropMode(OverlayView.DEFAULT_FREESTYLE_CROP_MODE)// 裁剪框拖动模式
572
                .isCropDragSmoothToCenter(true)// 裁剪框拖动时图片自动跟随居中
573
                .circleDimmedLayer(true)// 是否开启圆形裁剪
574
                .isDragFrame(true)//是否可拖动裁剪框(固定)
575
                .showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
576
                .showCropGrid(false)//是否显示裁剪矩形网格 圆形裁剪时建议设为false
577
                .forResult(1);
523 578
    }
524 579
525 580
    private boolean checkText() {
@ -671,34 +726,30 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
671 726
                car_type = select_chexing;
672 727
                break;
673 728
            case 1:
674
                if (SDCardUtil.hasSdcard()) {
675
                    cropImageUri = Uri.fromFile(fileCropUri);
676
                    Uri newUri = Uri.parse(PhotoUtils.getPath(this, data.getData()));
677
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
678
                        newUri = FileProvider.getUriForFile(this, "com.electric.chargingpile.provider", new File(newUri.getPath()));
679
                    PhotoUtils.cropImageUri(this, newUri, cropImageUri, 1, 1, output_X, output_Y, 3);
680
                } else {
681
                    Toast.makeText(SkipUserInfoActivity.this, "设备没有SD卡!", Toast.LENGTH_SHORT).show();
682
                }
683
                break;
684
            // 如果是调用相机拍照时
685 729
            case 2:
686
                cropImageUri = Uri.fromFile(fileCropUri);
687
                PhotoUtils.cropImageUri(this, imageUri, cropImageUri, 1, 1, output_X, output_Y, 3);
688
                break;
689
690
            // 取得裁剪后的图片
691
            case 3:
692
                photo = imageZoom(PhotoUtils.getBitmapFromUri(cropImageUri, this));
693
                if (photo != null) {
694
                    iconPic.setImageBitmap(photo);
695
                }
730
                activityResult(data);
696 731
                break;
697 732
            default:
698 733
                break;
699 734
        }
700 735
        ;
701 736
    }
737
    private void activityResult(Intent data) {
738
        List<LocalMedia> medias = PictureSelector.obtainMultipleResult(data);
739
        if (medias != null && medias.size() > 0) {
740
            String path = "";
741
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
742
                path = medias.get(0).getAndroidQToPath();
743
            } else {
744
                path = medias.get(0).getPath();
745
            }
746
            photo = imageZoom(BitmapFactory.decodeFile(path));
747
            if (photo != null) {
748
                iconPic.setImageBitmap(photo);
749
            }
750
751
        }
752
    }
702 753
703 754
    private Bitmap imageZoom(Bitmap bm) {
704 755
        // 图片允许最大空间 单位:KB
@ -1000,7 +1051,7 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
1000 1051
                            //获取意向车型
1001 1052
                            if (bean.getStatus() == 2 && isCarIntendedModel) {
1002 1053
                                CarSeriesEntity entity = gson.fromJson(bean.getChexing(), CarSeriesEntity.class);
1003
                                if (mCarModelEntity == null){
1054
                                if (mCarModelEntity == null) {
1004 1055
                                    carModel.setText(entity.getSeriesName());
1005 1056
                                }
1006 1057
                                isCarIntendedModel = false;
@ -1055,7 +1106,7 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
1055 1106
    /**
1056 1107
     * 意向车型Event
1057 1108
     */
1058
    @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
1109
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
1059 1110
    public void onCarModelEvent(CarIntentModelEvent event) {
1060 1111
        if (event != null) {
1061 1112
            mCarModelEntity = event.getCarModelEntity();
@ -1084,7 +1135,7 @@ public class SkipUserInfoActivity extends Activity implements View.OnClickListen
1084 1135
        map.put("token", token);
1085 1136
1086 1137
        Gson gson = new Gson();
1087
        if (mCarModelEntity == null){
1138
        if (mCarModelEntity == null) {
1088 1139
            return;
1089 1140
        }
1090 1141
        String chexing = gson.toJson(mCarModelEntity);

+ 0 - 72
app/src/main/java/com/electric/chargingpile/activity/TestProgressActivity.java

@ -1,72 +0,0 @@
1
package com.electric.chargingpile.activity;
2
3
import android.app.Activity;
4
import android.graphics.Rect;
5
import android.graphics.drawable.Drawable;
6
import android.os.Bundle;
7
import android.os.Handler;
8
import android.os.Message;
9
import android.view.View;
10
11
import com.electric.chargingpile.R;
12
import com.electric.chargingpile.view.SaundProgressBar;
13
14
public class TestProgressActivity extends Activity {
15
16
    private SaundProgressBar mPbar;
17
    private int progress = 0;
18
    private Message message;
19
    private Handler handler = new Handler() {
20
21
        @Override
22
        public void handleMessage(Message msg) {
23
            // TODO Auto-generated method stub
24
            super.handleMessage(msg);
25
            int p = msg.what;
26
            mPbar.setProgress(p);
27
        }
28
29
    };
30
31
    @Override
32
    protected void onCreate(Bundle savedInstanceState) {
33
        super.onCreate(savedInstanceState);
34
        setContentView(R.layout.activity_test_progress);
35
36
        mPbar = (SaundProgressBar) this.findViewById(R.id.regularprogressbar);
37
        mPbar.setMax(100);
38
39
        Drawable indicator = getResources().getDrawable(
40
                R.drawable.progress_indicator);
41
        Rect bounds = new Rect(0, 0, indicator.getIntrinsicWidth() + 5,
42
                indicator.getIntrinsicHeight());
43
        indicator.setBounds(bounds);
44
45
        mPbar.setProgressIndicator(indicator);
46
        mPbar.setProgress(0);
47
        mPbar.setVisibility(View.VISIBLE);
48
49
        new Thread(runnable).start();
50
    }
51
52
    Runnable runnable = new Runnable() {
53
54
        @Override
55
        public void run() {
56
            message = handler.obtainMessage();
57
            // TODO Auto-generated method stub
58
            try {
59
                for (int i = 1; i <= 100; i++) {
60
                    int x = progress++;
61
                    message.what = x;
62
                    handler.sendEmptyMessage(message.what);
63
                    Thread.sleep(1000);
64
                }
65
66
            } catch (InterruptedException e) {
67
                // TODO Auto-generated catch block
68
                e.printStackTrace();
69
            }
70
        }
71
    };
72
}

+ 0 - 18
app/src/main/java/com/electric/chargingpile/activity/TesttActivity.java

@ -1,18 +0,0 @@
1
package com.electric.chargingpile.activity;
2
3
import android.os.Bundle;
4
5
import com.electric.chargingpile.R;
6
import com.zhy.autolayout.AutoLayout;
7
import com.zhy.autolayout.AutoLayoutActivity;
8
9
public class TesttActivity extends AutoLayoutActivity {
10
11
    @Override
12
    protected void onCreate(Bundle savedInstanceState) {
13
        super.onCreate(savedInstanceState);
14
        setContentView(R.layout.activity_testt);
15
        AutoLayout.getInstance().auto(this, true);
16
    }
17
18
}

+ 5 - 7
app/src/main/java/com/electric/chargingpile/activity/UserCenterActivity.java

@ -17,14 +17,9 @@ import android.net.ConnectivityManager;
17 17
import android.net.NetworkInfo;
18 18
import android.net.Uri;
19 19
import android.os.Bundle;
20
import android.os.Environment;
21 20
import android.os.Handler;
22 21
import android.os.Message;
23 22
import android.os.Process;
24
25
import androidx.annotation.NonNull;
26
27
import android.text.TextUtils;
28 23
import android.util.Log;
29 24
import android.view.KeyEvent;
30 25
import android.view.View;
@ -37,6 +32,8 @@ import android.widget.TextView;
37 32
import android.widget.Toast;
38 33
import android.widget.ToggleButton;
39 34
35
import androidx.annotation.NonNull;
36
40 37
import com.amap.api.services.weather.LocalDayWeatherForecast;
41 38
import com.amap.api.services.weather.LocalWeatherForecast;
42 39
import com.amap.api.services.weather.LocalWeatherForecastResult;
@ -56,6 +53,7 @@ import com.electric.chargingpile.util.JsonUtils;
56 53
import com.electric.chargingpile.util.LoadingDialog;
57 54
import com.electric.chargingpile.util.NetUtil;
58 55
import com.electric.chargingpile.util.OkHttpUtil;
56
import com.electric.chargingpile.util.PhotoUtils;
59 57
import com.electric.chargingpile.util.PicassoUtil;
60 58
import com.electric.chargingpile.util.ScreenUtils;
61 59
import com.electric.chargingpile.util.Util;
@ -527,7 +525,7 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
527 525
//        }
528 526
        if (MainApplication.userIcon.equals("V")) {
529 527
//            Log.e("1111", "11111");
530
            usericonbt = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + File.separator + "d1ev/usericon");
528
            usericonbt = BitmapFactory.decodeFile(PhotoUtils.CACHE_DIR + "d1ev/usericon");
531 529
            userIcon.setImageBitmap(usericonbt);
532 530
        } else if (MainApplication.userIcon.equals("")) {
533 531
//            Log.e("2222", "22222");
@ -548,7 +546,7 @@ public class UserCenterActivity extends Activity implements View.OnClickListener
548 546
    }
549 547
550 548
    public void saveBitmap(Bitmap mBitmap) {
551
        String dir_path = Environment.getExternalStorageDirectory() + File.separator + "d1ev/";
549
        String dir_path = PhotoUtils.CACHE_DIR + "d1ev/";
552 550
        File directory = new File(dir_path);
553 551
        File f = new File(dir_path, "usericon");
554 552
        try {

+ 91 - 82
app/src/main/java/com/electric/chargingpile/activity/UserInfoActivity.java

@ -19,14 +19,9 @@ import android.graphics.drawable.Drawable;
19 19
import android.net.Uri;
20 20
import android.os.Build;
21 21
import android.os.Bundle;
22
import android.os.Environment;
23 22
import android.os.Handler;
24 23
import android.os.Looper;
25 24
import android.os.Message;
26
import android.provider.MediaStore;
27
28
import androidx.core.content.FileProvider;
29
30 25
import android.text.TextUtils;
31 26
import android.util.Log;
32 27
import android.view.Gravity;
@ -55,11 +50,10 @@ import com.electric.chargingpile.application.MainApplication;
55 50
import com.electric.chargingpile.data.CarOwnerCertificateBean;
56 51
import com.electric.chargingpile.data.Cars;
57 52
import com.electric.chargingpile.data.Province;
53
import com.electric.chargingpile.engine.GlideEngine;
58 54
import com.electric.chargingpile.entity.CarModelEntity;
59 55
import com.electric.chargingpile.entity.CarSeriesEntity;
60 56
import com.electric.chargingpile.event.CarIntentModelEvent;
61
import com.electric.chargingpile.event.CarModelEvent;
62
import com.electric.chargingpile.manager.PreferenceManager;
63 57
import com.electric.chargingpile.manager.ProfileManager;
64 58
import com.electric.chargingpile.util.BarColorUtil;
65 59
import com.electric.chargingpile.util.DES3;
@ -71,16 +65,21 @@ import com.electric.chargingpile.util.PhotoUtils;
71 65
import com.electric.chargingpile.util.StatusConstants;
72 66
import com.electric.chargingpile.util.ToastUtil;
73 67
import com.electric.chargingpile.util.UploadUtil;
74
import com.electric.chargingpile.view.AlertDialogTwo;
68
import com.electric.chargingpile.util.Util;
75 69
import com.electric.chargingpile.view.CustomProgressDialog;
76 70
import com.electric.chargingpile.view.RoundImageView;
77
import com.electric.chargingpile.view.xrichtext.SDCardUtil;
78 71
import com.google.gson.Gson;
72
import com.luck.picture.lib.PictureSelector;
73
import com.luck.picture.lib.animators.AnimationType;
74
import com.luck.picture.lib.config.PictureConfig;
75
import com.luck.picture.lib.config.PictureMimeType;
76
import com.luck.picture.lib.entity.LocalMedia;
79 77
import com.squareup.okhttp.Request;
80 78
import com.squareup.okhttp.Response;
81 79
import com.squareup.picasso.Picasso;
82 80
import com.squareup.picasso.Target;
83 81
import com.umeng.analytics.MobclickAgent;
82
import com.yalantis.ucrop.view.OverlayView;
84 83
import com.zhy.http.okhttp.OkHttpUtils;
85 84
import com.zhy.http.okhttp.callback.StringCallback;
86 85
@ -93,8 +92,6 @@ import org.json.JSONObject;
93 92
94 93
import java.io.ByteArrayInputStream;
95 94
import java.io.ByteArrayOutputStream;
96
import java.io.File;
97
import java.io.FileOutputStream;
98 95
import java.io.IOException;
99 96
import java.net.URLEncoder;
100 97
import java.util.ArrayList;
@ -145,10 +142,7 @@ public class UserInfoActivity extends Activity implements View.OnClickListener,
145 142
    private TextView tv_point;
146 143
    private RelativeLayout rl_point;
147 144
    private android.view.animation.Animation animation;
148
    private File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/photo.jpg");
149
    private File fileCropUri = new File(Environment.getExternalStorageDirectory().getPath() + "/crop_photo.jpg");
150
    private Uri imageUri;
151
    private Uri cropImageUri;
145
152 146
    private static final int RC_CAMERA_PERM = 123;
153 147
    private LoadingDialog loadDialog;
154 148
    // -2 -> 去认证, -1 -> 认证失败,0 -> 审核中,1 -> 表示通过审核,2 -> 表示意向车型。
@ -520,11 +514,8 @@ public class UserInfoActivity extends Activity implements View.OnClickListener,
520 514
        btn_two.setOnClickListener(new View.OnClickListener() {
521 515
            @Override
522 516
            public void onClick(View view) {
523
                Intent intent = new Intent(Intent.ACTION_PICK, null);
524
                intent.setDataAndType(
525
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
526
                        "image/*");
527
                startActivityForResult(intent, 1);
517
                openPhotoAlbum();
518
528 519
                popupWindow.dismiss();
529 520
            }
530 521
        });
@ -533,6 +524,7 @@ public class UserInfoActivity extends Activity implements View.OnClickListener,
533 524
    }
534 525
535 526
527
536 528
    public void shite(String s) {
537 529
538 530
        Map<String, String> par = new HashMap<String, String>();
@ -587,16 +579,67 @@ public class UserInfoActivity extends Activity implements View.OnClickListener,
587 579
     * @param view
588 580
     */
589 581
    public void takePhoto(View view) {
590
        if (SDCardUtil.hasSdcard()) {
591
            imageUri = Uri.fromFile(fileUri);
592
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
593
                //通过FileProvider创建一个content类型的Uri
594
                imageUri = FileProvider.getUriForFile(UserInfoActivity.this, "com.electric.chargingpile.provider", fileUri);
595
            PhotoUtils.takePicture(UserInfoActivity.this, imageUri, 2);
596
        } else {
597
            Toast.makeText(UserInfoActivity.this, "设备没有SD卡!", Toast.LENGTH_SHORT).show();
598
            Log.e("asd", "设备没有SD卡");
599
        }
582
583
        PictureSelector.create(this)
584
                .openCamera(PictureMimeType.ofImage())
585
                .selectionMode(PictureConfig.SINGLE)
586
                .isSingleDirectReturn(true)
587
                .isCompress(true)//是否压缩
588
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
589
                .isGif(false)//是否显示gif
590
                .isAndroidQTransform(true)
591
                .imageEngine(GlideEngine.createGlideEngine())
592
                .isWeChatStyle(false)// 是否开启微信图片选择风格
593
                .isUseCustomCamera(false)// 是否使用自定义相机
594
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
595
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
596
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
597
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
598
                .imageSpanCount(4)// 每行显示个数
599
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
600
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
601
                .isEnableCrop(true)
602
                .rotateEnabled(false)//裁剪是否可旋转图片
603
                .setCircleStrokeWidth(8)//设置圆形裁剪边框粗细
604
                .freeStyleCropMode(OverlayView.DEFAULT_FREESTYLE_CROP_MODE)// 裁剪框拖动模式
605
                .isCropDragSmoothToCenter(true)// 裁剪框拖动时图片自动跟随居中
606
                .circleDimmedLayer(true)// 是否开启圆形裁剪
607
                .isDragFrame(true)//是否可拖动裁剪框(固定)
608
                .showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
609
                .showCropGrid(false)//是否显示裁剪矩形网格 圆形裁剪时建议设为false
610
                .forResult(2);
611
    }
612
    private void openPhotoAlbum() {
613
        PictureSelector.create(UserInfoActivity.this)
614
                .openGallery(PictureMimeType.ofImage())
615
                .isCamera(false)//列表是否显示拍照按钮
616
                .selectionMode(PictureConfig.SINGLE)
617
                .isSingleDirectReturn(true)//PictureConfig.SINGLE模式下是否直接返回
618
                .isCompress(true)//是否压缩
619
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
620
                .isGif(false)//是否显示gif
621
                .isAndroidQTransform(true)
622
                .imageEngine(GlideEngine.createGlideEngine())
623
                .isWeChatStyle(false)// 是否开启微信图片选择风格
624
                .isUseCustomCamera(false)// 是否使用自定义相机
625
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
626
                .setPictureStyle(Util.getWhiteStyle(UserInfoActivity.this))// 动态自定义相册主题
627
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
628
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
629
                .imageSpanCount(4)// 每行显示个数
630
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
631
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
632
                .rotateEnabled(false)//裁剪是否可旋转图片
633
                .isEnableCrop(true)
634
                .rotateEnabled(false)//裁剪是否可旋转图片
635
                .setCircleStrokeWidth(8)//设置圆形裁剪边框粗细
636
                .freeStyleCropMode(OverlayView.DEFAULT_FREESTYLE_CROP_MODE)// 裁剪框拖动模式
637
                .isCropDragSmoothToCenter(true)// 裁剪框拖动时图片自动跟随居中
638
                .circleDimmedLayer(true)// 是否开启圆形裁剪
639
                .isDragFrame(true)//是否可拖动裁剪框(固定)
640
                .showCropFrame(false)// 是否显示裁剪矩形边框 圆形裁剪时建议设为false
641
                .showCropGrid(false)//是否显示裁剪矩形网格 圆形裁剪时建议设为false
642
                .forResult(1);
600 643
    }
601 644
602 645
    @AfterPermissionGranted(RC_CAMERA_PERM)
@ -714,37 +757,34 @@ public class UserInfoActivity extends Activity implements View.OnClickListener,
714 757
715 758
716 759
        switch (requestCode) {
717
            // 如果是直接从相册获取
718 760
            case 1:
719
                if (SDCardUtil.hasSdcard()) {
720
                    cropImageUri = Uri.fromFile(fileCropUri);
721
                    Uri newUri = Uri.parse(PhotoUtils.getPath(this, data.getData()));
722
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
723
                        newUri = FileProvider.getUriForFile(this, "com.electric.chargingpile.provider", new File(newUri.getPath()));
724
                    PhotoUtils.cropImageUri(this, newUri, cropImageUri, 1, 1, output_X, output_Y, 3);
725
                } else {
726
                    Toast.makeText(UserInfoActivity.this, "设备没有SD卡!", Toast.LENGTH_SHORT).show();
727
                }
728
                break;
729
            // 如果是调用相机拍照时
730 761
            case 2:
731
                cropImageUri = Uri.fromFile(fileCropUri);
732
                PhotoUtils.cropImageUri(this, imageUri, cropImageUri, 1, 1, output_X, output_Y, 3);
762
                activityResult(data);
733 763
                break;
734 764
735
            // 取得裁剪后的图片
736
            case 3:
737
                photo = imageZoom(PhotoUtils.getBitmapFromUri(cropImageUri, this));
738
                if (photo != null) {
739
                    iconPic.setImageBitmap(photo);
740
                }
741
                break;
742 765
            default:
743 766
                break;
744 767
        }
745 768
        ;
746 769
    }
747 770
771
    private void activityResult(Intent data) {
772
        List<LocalMedia> medias = PictureSelector.obtainMultipleResult(data);
773
        if (medias != null && medias.size() > 0) {
774
            String path = "";
775
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
776
                path = medias.get(0).getAndroidQToPath();
777
            } else {
778
                path = medias.get(0).getPath();
779
            }
780
            photo = imageZoom(BitmapFactory.decodeFile(path));
781
            if (photo != null) {
782
                iconPic.setImageBitmap(photo);
783
            }
784
785
        }
786
    }
787
748 788
    private Bitmap imageZoom(Bitmap bm) {
749 789
        // 图片允许最大空间 单位:KB
750 790
        double maxSize = 40.00;
@ -871,37 +911,6 @@ public class UserInfoActivity extends Activity implements View.OnClickListener,
871 911
        return output;
872 912
    }
873 913
874
    public void saveBitmap(Bitmap mBitmap) {
875
        String dir_path = Environment.getExternalStorageDirectory() + File.separator + "d1ev/";
876
        File directory = new File(dir_path);
877
        File f = new File(dir_path, "usericon");
878
        try {
879
            if (!directory.exists()) {
880
                directory.mkdir();//没有目录先创建目录
881
            }
882
            f.createNewFile();
883
        } catch (IOException e) {
884
            // TODO Auto-generated catch block
885
        }
886
        FileOutputStream fOut = null;
887
        try {
888
            fOut = new FileOutputStream(f);
889
        } catch (Exception e) {
890
            e.printStackTrace();
891
        }
892
        mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
893
        try {
894
            fOut.flush();
895
        } catch (IOException e) {
896
            e.printStackTrace();
897
        }
898
        try {
899
            fOut.close();
900
        } catch (IOException e) {
901
            e.printStackTrace();
902
        }
903
    }
904
905 914
906 915
    Handler handle = new Handler(Looper.getMainLooper()) {
907 916
        public void handleMessage(Message msg) {

+ 2 - 31
app/src/main/java/com/electric/chargingpile/activity/WelcomeActivity.java

@ -48,6 +48,7 @@ import com.electric.chargingpile.util.BarColorUtil;
48 48
import com.electric.chargingpile.util.DES3;
49 49
import com.electric.chargingpile.util.JsonUtils;
50 50
import com.electric.chargingpile.util.OkHttpUtil;
51
import com.electric.chargingpile.util.PhotoUtils;
51 52
import com.electric.chargingpile.util.SystemTypeUtil;
52 53
import com.electric.chargingpile.view.AlertDialogTwo;
53 54
import com.electric.chargingpile.view.ViewPagerAdapter;
@ -100,7 +101,7 @@ public class WelcomeActivity extends Activity {
100 101
    public static String canCost = "";
101 102
    private static final int RC_CAMERA_PERM = 123;
102 103
    private static final int RC_SAVE_PERM = 124;
103
    private static final String MAP_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz_map");
104
    private static final String MAP_FILE_PATH = getPath(PhotoUtils.CACHE_DIR + "/" + "cdz_map");
104 105

105 106

106 107
    private ImageView oneIv, twoIv, threeIv, fourIv;
@ -469,36 +470,6 @@ public class WelcomeActivity extends Activity {
469 470
    }
470 471

471 472

472
    public void saveBitmap(Bitmap mBitmap) {
473
        String dir_path = Environment.getExternalStorageDirectory() + File.separator + "d1ev/";
474
        File directory = new File(dir_path);
475
        File f = new File(dir_path, "welcome_pic");
476
        try {
477
            if (!directory.exists()) {
478
                directory.mkdir();//没有目录先创建目录
479
            }
480
            f.createNewFile();
481
        } catch (IOException e) {
482
            // TODO Auto-generated catch block
483
        }
484
        FileOutputStream fOut = null;
485
        try {
486
            fOut = new FileOutputStream(f);
487
        } catch (Exception e) {
488
            e.printStackTrace();
489
        }
490
        mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
491
        try {
492
            fOut.flush();
493
        } catch (IOException e) {
494
            e.printStackTrace();
495
        }
496
        try {
497
            fOut.close();
498
        } catch (IOException e) {
499
            e.printStackTrace();
500
        }
501
    }
502 473

503 474
    private void getStartPic() {
504 475
        new Thread(new Runnable() {

+ 52 - 151
app/src/main/java/com/electric/chargingpile/activity/ZhanCommentActivity.java

@ -18,7 +18,7 @@ import android.graphics.drawable.ColorDrawable;
18 18
import android.net.Uri;
19 19
import android.os.Build;
20 20
import android.os.Bundle;
21
import android.os.Environment;
21
22 22
import android.os.Handler;
23 23
import android.os.Message;
24 24
import android.provider.MediaStore;
@ -50,6 +50,7 @@ import com.electric.chargingpile.application.MainApplication;
50 50
import com.electric.chargingpile.data.CommentsBean;
51 51
import com.electric.chargingpile.data.MyOtto;
52 52
import com.electric.chargingpile.data.RObject;
53
import com.electric.chargingpile.engine.GlideEngine;
53 54
import com.electric.chargingpile.util.BarColorUtil;
54 55
import com.electric.chargingpile.util.Bimp;
55 56
import com.electric.chargingpile.util.DES3;
@ -59,18 +60,22 @@ import com.electric.chargingpile.util.ImageUtils;
59 60
import com.electric.chargingpile.util.JsonUtils;
60 61
import com.electric.chargingpile.util.LoadingDialog;
61 62
import com.electric.chargingpile.util.Md5Util;
63
import com.electric.chargingpile.util.PhotoUtils;
62 64
import com.electric.chargingpile.util.PublicWayONE;
63 65
import com.electric.chargingpile.util.Res;
64 66
import com.electric.chargingpile.util.ScreenUtils;
65 67
import com.electric.chargingpile.util.StatusConstants;
66 68
import com.electric.chargingpile.util.ToastUtil;
67 69
import com.electric.chargingpile.util.UploadUtil;
70
import com.electric.chargingpile.util.Util;
68 71
import com.electric.chargingpile.view.REditText;
69 72
import com.electric.chargingpile.view.RatingBarView;
70
import com.zhihu.matisse.Matisse;
71
import com.zhihu.matisse.MimeType;
72
import com.zhihu.matisse.engine.impl.GlideEngine;
73
import com.zhihu.matisse.internal.entity.CaptureStrategy;
73
74
import com.luck.picture.lib.PictureSelector;
75
import com.luck.picture.lib.animators.AnimationType;
76
import com.luck.picture.lib.config.PictureConfig;
77
import com.luck.picture.lib.config.PictureMimeType;
78
import com.luck.picture.lib.entity.LocalMedia;
74 79
import com.zhy.http.okhttp.OkHttpUtils;
75 80
import com.zhy.http.okhttp.callback.StringCallback;
76 81
import com.zhy.view.flowlayout.FlowLayout;
@ -127,12 +132,12 @@ public class ZhanCommentActivity extends Activity implements View.OnClickListene
127 132
    private String select_s = "";
128 133
    private String select_ss = "";
129 134
    private TextView tv_grade, tv_point;
130
    private File tempFile;
135
131 136
    private static String PHOTO_FILE_NAME = "";
132
    private static final String PHOTO_FILE_PATH = getPath(Environment.getExternalStorageDirectory() + "/" + "cdz");
137
    private static final String PHOTO_FILE_PATH = getPath(PhotoUtils.CACHE_DIR);
133 138
    public static Bitmap bimap;
134
    private PopupWindow pop = null;
135
    private LinearLayout ll_popup;
139
140
136 141
    private GridView noScrollgridview;
137 142
    private GridAdapter adapter;
138 143
    private static final int PHOTO_REQUEST_CAMERA = 1;
@ -177,7 +182,7 @@ public class ZhanCommentActivity extends Activity implements View.OnClickListene
177 182
            super.handleMessage(msg);
178 183
        }
179 184
    };
180
185
    private List<LocalMedia> mSelectionData =new ArrayList<LocalMedia>();
181 186
    @Override
182 187
    protected void onCreate(Bundle savedInstanceState) {
183 188
        super.onCreate(savedInstanceState);
@ -188,9 +193,6 @@ public class ZhanCommentActivity extends Activity implements View.OnClickListene
188 193
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
189 194
        networkChangeReceiver = new NetworkChangeReceiver();
190 195
        registerReceiver(networkChangeReceiver, intentFilter);
191
        long appTime1 = System.currentTimeMillis() / 1000;
192
        PHOTO_FILE_NAME = "android" + appTime1 + ".jpg";
193
        tempFile = getFile(PHOTO_FILE_PATH + "/" + PHOTO_FILE_NAME);
194 196
        MyOtto.getInstance().unregister(this);
195 197
        Res.init(this);
196 198
        bimap = BitmapFactory.decodeResource(
@ -441,53 +443,6 @@ public class ZhanCommentActivity extends Activity implements View.OnClickListene
441 443
    }
442 444
443 445
    public void Init() {
444
        pop = new PopupWindow(ZhanCommentActivity.this);
445
        View view = getLayoutInflater().inflate(R.layout.item_popupwindows, null);
446
        ll_popup = (LinearLayout) view.findViewById(R.id.ll_popup);
447
448
        pop.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
449
        pop.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
450
        pop.setBackgroundDrawable(new BitmapDrawable());
451
        pop.setFocusable(true);
452
        pop.setOutsideTouchable(true);
453
        pop.setContentView(view);
454
455
456
        final RelativeLayout parent = (RelativeLayout) view.findViewById(R.id.parent);
457
        Button bt1 = (Button) view.findViewById(R.id.item_popupwindows_camera);
458
        Button bt2 = (Button) view.findViewById(R.id.item_popupwindows_Photo);
459
        Button bt3 = (Button) view.findViewById(R.id.item_popupwindows_cancel);
460
        parent.setOnClickListener(new View.OnClickListener() {
461
462
            @Override
463
            public void onClick(View v) {
464
                // TODO Auto-generated method stub
465
                pop.dismiss();
466
                ll_popup.clearAnimation();
467
            }
468
        });
469
        bt1.setOnClickListener(new View.OnClickListener() {
470
            public void onClick(View v) {
471
                photo();
472
                pop.dismiss();
473
                ll_popup.clearAnimation();
474
            }
475
        });
476
        bt2.setOnClickListener(new View.OnClickListener() {
477
            public void onClick(View v) {
478
                Intent intent = new Intent(ZhanCommentActivity.this, AlbumActivityComment.class);
479
                startActivity(intent);
480
                overridePendingTransition(R.anim.activity_translate_in, R.anim.activity_translate_out);
481
                pop.dismiss();
482
                ll_popup.clearAnimation();
483
            }
484
        });
485
        bt3.setOnClickListener(new View.OnClickListener() {
486
            public void onClick(View v) {
487
                pop.dismiss();
488
                ll_popup.clearAnimation();
489
            }
490
        });
491 446
492 447
        noScrollgridview = (GridView) findViewById(R.id.noScrollgridview);
493 448
        noScrollgridview.setSelector(new ColorDrawable(Color.TRANSPARENT));
@ -518,14 +473,25 @@ public class ZhanCommentActivity extends Activity implements View.OnClickListene
518 473
     * 调用图库选择
519 474
     */
520 475
    private void callGallery() {
521
        Matisse.from(ZhanCommentActivity.this)
522
                .choose(MimeType.of(MimeType.JPEG, MimeType.PNG, MimeType.GIF))
523
                .showSingleMediaType(true)
524
                .countable(true)
525
                .maxSelectable(PIC_NUM - Bimp.tempSelectBitmap.size())
526
                .capture(true)
527
                .captureStrategy(new CaptureStrategy(true, "com.electric.chargingpile.provider"))
528
                .imageEngine(new GlideEngine())
476
        PictureSelector.create(this)
477
                .openGallery(PictureMimeType.ofImage())
478
                .maxSelectNum(PIC_NUM)
479
                .selectionMode(PictureConfig.MULTIPLE)
480
                .selectionData(mSelectionData)//是否传入已选图片
481
                .isCompress(true)//是否压缩
482
                .isPreviewEggs(true)//预览图片时是否增强左右滑动图片体验
483
                .isGif(true)//是否显示gif
484
                .isAndroidQTransform(true)
485
                .imageEngine(GlideEngine.createGlideEngine())
486
                .isWeChatStyle(false)// 是否开启微信图片选择风格
487
                .isUseCustomCamera(false)// 是否使用自定义相机
488
                .isPageStrategy(true)// 是否开启分页策略 & 每页多少条;默认开启
489
                .setPictureStyle(Util.getWhiteStyle(this))// 动态自定义相册主题
490
                .setRecyclerAnimationMode(AnimationType.SLIDE_IN_BOTTOM_ANIMATION)// 列表动画效果
491
                .isMaxSelectEnabledMask(true)// 选择数到了最大阀值列表是否启用蒙层效果
492
                .imageSpanCount(4)// 每行显示个数
493
                .isReturnEmpty(false)// 未选择数据时点击按钮是否可以返回
494
                .isAutomaticTitleRecyclerTop(true)//图片列表超过一屏连续点击顶部标题栏快速回滚至顶部
529 495
                .forResult(REQUEST_CODE_CHOOSE);
530 496
    }
531 497
@ -555,15 +521,25 @@ public class ZhanCommentActivity extends Activity implements View.OnClickListene
555 521
            @Override
556 522
            public void subscribe(ObservableEmitter<String> subscriber) throws Exception {
557 523
                try {
558
                    List<Uri> uriList = Matisse.obtainResult(data);
559
                    for (Uri uri : uriList) {
560
                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
561
                        File file = FileUtils.from(ZhanCommentActivity.this, uri);
562
563
                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
564
                        bitmap = imageZoom(bitmap);
524
//                    List<Uri> uriList = Matisse.obtainResult(data);
525
                    mSelectionData= PictureSelector.obtainMultipleResult(data);
526
                    for (LocalMedia media : mSelectionData) {
527
//                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
528
//                        File file = FileUtils.from(ZhanCommentActivity.this, uri);
529
//
530
//                        bitmap = FileUtils.rotateIfRequired(file, bitmap);
531
//                        bitmap = imageZoom(bitmap);
532
//                        ImageItem takePhoto = new ImageItem();
533
//                        takePhoto.setBitmap(bitmap);
534
//                        Bimp.tempSelectBitmap.add(takePhoto);
535
                        String path="";
536
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
537
                            path= media.getAndroidQToPath();
538
                        }else{
539
                            path=media.getPath();
540
                        }
565 541
                        ImageItem takePhoto = new ImageItem();
566
                        takePhoto.setBitmap(bitmap);
542
                        takePhoto.setBitmap(imageZoom(BitmapFactory.decodeFile(path)));
567 543
                        Bimp.tempSelectBitmap.add(takePhoto);
568 544
                        subscriber.onNext("");
569 545
                    }
@ -1045,82 +1021,7 @@ public class ZhanCommentActivity extends Activity implements View.OnClickListene
1045 1021
        }
1046 1022
    }
1047 1023
1048
    public void photo() {
1049
        if (hasSdcard()) {
1050
            int currentapiVersion = Build.VERSION.SDK_INT;
1051
            Log.e("currentapiVersion", "currentapiVersion====>" + currentapiVersion);
1052
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//���������
1053
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
1054
            startActivityForResult(intent, PHOTO_REQUEST_CAMERA);
1055
        }
1056
    }
1057
1058
    private boolean hasSdcard() {
1059
        if (Environment.getExternalStorageState().equals(
1060
                Environment.MEDIA_MOUNTED)) {
1061
            return true;
1062
        } else {
1063
            return false;
1064
        }
1065
    }
1066 1024
1067
    private void crop(Uri uri, Uri cutImgUri) {
1068
        // �ü�ͼƬ��ͼ
1069
        Intent intent = new Intent("com.android.camera.action.CROP");
1070
        intent.setDataAndType(getImageContentUri(this, tempFile), "image/*");
1071
1072
        intent.putExtra("crop", "true");
1073
        // �ü���ı�����1��1
1074
//        intent.putExtra("aspectX", 16);
1075
//        intent.putExtra("aspectY", 9);
1076
//        // �ü������ͼƬ�ijߴ��С
1077
//        intent.putExtra("outputX", 900);
1078
//        intent.putExtra("outputY", 540);
1079
//        intent.putExtra("scale", false);
1080
1081
        // ͼƬ��ʽ
1082
        intent.putExtra("outputFormat", "JPEG");
1083
        intent.putExtra("noFaceDetection", true);// ȡ������ʶ��
1084
        intent.putExtra("return-data", false);// true:������uri��false������uri
1085
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));//д���ȡ��ͼƬ
1086
        startActivityForResult(intent, PHOTO_REQUEST_CUT);
1087
    }
1088
1089
    public static Uri getImageContentUri(Context context, File imageFile) {
1090
        String filePath = imageFile.getAbsolutePath();
1091
        Cursor cursor = context.getContentResolver().query(
1092
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
1093
                new String[]{MediaStore.Images.Media._ID},
1094
                MediaStore.Images.Media.DATA + "=? ",
1095
                new String[]{filePath}, null);
1096
1097
        if (cursor != null && cursor.moveToFirst()) {
1098
            int id = cursor.getInt(cursor
1099
                    .getColumnIndex(MediaStore.MediaColumns._ID));
1100
            Uri baseUri = Uri.parse("content://media/external/images/media");
1101
            return Uri.withAppendedPath(baseUri, "" + id);
1102
        } else {
1103
            if (imageFile.exists()) {
1104
                ContentValues values = new ContentValues();
1105
                values.put(MediaStore.Images.Media.DATA, filePath);
1106
                return context.getContentResolver().insert(
1107
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
1108
            } else {
1109
                return null;
1110
            }
1111
        }
1112
    }
1113
1114
    public Bitmap decodeUriAsBitmap(Uri uri) {
1115
        Bitmap bitmap = null;
1116
        try {
1117
            bitmap = BitmapFactory.decodeStream(this.getContentResolver().openInputStream(uri));
1118
        } catch (FileNotFoundException e) {
1119
            e.printStackTrace();
1120
            return null;
1121
        }
1122
        return bitmap;
1123
    }
1124 1025
1125 1026
    protected void onRestart() {
1126 1027
        adapter.update();

+ 6 - 55
app/src/main/java/com/electric/chargingpile/activity/ZoomingPhotoTextActivity.java

@ -1,15 +1,7 @@
1 1
package com.electric.chargingpile.activity;
2 2
3 3
import android.content.Intent;
4
import android.graphics.Bitmap;
5 4
import android.os.Bundle;
6
import android.os.Environment;
7
import android.provider.MediaStore;
8
import androidx.fragment.app.Fragment;
9
import androidx.fragment.app.FragmentActivity;
10
import androidx.fragment.app.FragmentManager;
11
import androidx.fragment.app.FragmentStatePagerAdapter;
12
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
13 5
import android.text.TextUtils;
14 6
import android.view.View;
15 7
import android.view.Window;
@ -20,6 +12,12 @@ import android.widget.ScrollView;
20 12
import android.widget.TextView;
21 13
import android.widget.Toast;
22 14
15
import androidx.fragment.app.Fragment;
16
import androidx.fragment.app.FragmentActivity;
17
import androidx.fragment.app.FragmentManager;
18
import androidx.fragment.app.FragmentStatePagerAdapter;
19
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
20
23 21
import com.electric.chargingpile.R;
24 22
import com.electric.chargingpile.application.MainApplication;
25 23
import com.electric.chargingpile.data.TopicDetailBean;
@ -34,10 +32,6 @@ import com.umeng.analytics.MobclickAgent;
34 32
import com.zhy.http.okhttp.OkHttpUtils;
35 33
import com.zhy.http.okhttp.callback.StringCallback;
36 34
37
import java.io.File;
38
import java.io.FileNotFoundException;
39
import java.io.FileOutputStream;
40
import java.io.IOException;
41 35
import java.util.ArrayList;
42 36
import java.util.HashMap;
43 37
import java.util.Map;
@ -212,49 +206,6 @@ public class ZoomingPhotoTextActivity extends FragmentActivity implements PhotoV
212 206
        // finish();
213 207
    }
214 208
215
    public void saveBitmap(String picName, Bitmap bm) {
216
        if (bm != null) {
217
            String result = "";
218
            String folder = Environment.getExternalStorageDirectory().getAbsoluteFile() + File.separator + "touch/img/";
219
            File folderFile = new File(folder);
220
            try {
221
                if (!folderFile.exists()) {
222
                    folderFile.mkdirs();
223
                }
224
                File f = new File(folder, picName);
225
                if (!f.exists()) {
226
                    f.createNewFile();
227
                }
228
229
                FileOutputStream out = new FileOutputStream(f);
230
                bm.compress(Bitmap.CompressFormat.PNG, 90, out);
231
                out.flush();
232
                out.close();
233
                result = "success_sd";
234
                // 其次把文件插入到系统图库
235
                MediaStore.Images.Media.insertImage(getBaseContext().getContentResolver(),
236
                        f.getAbsolutePath(), picName, null);
237
                result = "success";
238
            } catch (FileNotFoundException e) {
239
                // TODO Auto-generated catch block
240
                e.printStackTrace();
241
                result = "fail";
242
            } catch (IOException e) {
243
                // TODO Auto-generated catch block
244
                e.printStackTrace();
245
                result = "fail";
246
            }
247
//            bm.recycle();
248
//            bm = null;
249
            if ("success".equals(result)) {
250
                Toast.makeText(this, "已成功保存到相册", Toast.LENGTH_SHORT).show();
251
            } else if ("success_sd".equals(result)) {
252
                Toast.makeText(this, "已成功保存到内存卡", Toast.LENGTH_SHORT).show();
253
            } else {
254
                Toast.makeText(this, "保存失败", Toast.LENGTH_SHORT).show();
255
            }
256
        }
257
    }
258 209
259 210
    @Override
260 211
    public void onClick(View v) {

+ 4 - 4
app/src/main/java/com/electric/chargingpile/application/MainApplication.java

@ -5,7 +5,7 @@ import android.content.Context;
5 5
import android.database.sqlite.SQLiteDatabase;
6 6
import android.graphics.Bitmap;
7 7
import android.os.Build;
8
import android.os.Environment;
8

9 9
import android.os.StrictMode;
10 10
import android.text.TextUtils;
11 11
import android.util.Log;
@ -27,6 +27,7 @@ import com.electric.chargingpile.gen.DaoSession;
27 27
import com.electric.chargingpile.manager.ProfileManager;
28 28
import com.electric.chargingpile.util.DES3;
29 29
import com.electric.chargingpile.util.JsonUtils;
30
import com.electric.chargingpile.util.PhotoUtils;
30 31
import com.electric.chargingpile.util.SharedPreferencesHelper;
31 32
import com.google.gson.Gson;
32 33
import com.mob.MobSDK;
@ -38,7 +39,6 @@ import com.nostra13.universalimageloader.core.assist.ImageScaleType;
38 39
import com.tencent.bugly.crashreport.CrashReport;
39 40
import com.zhy.http.okhttp.OkHttpUtils;
40 41
import com.zhy.http.okhttp.callback.StringCallback;
41
import com.zhy.http.okhttp.log.LoggerInterceptor;
42 42

43 43
import java.io.BufferedReader;
44 44
import java.io.BufferedWriter;
@ -56,7 +56,6 @@ import java.util.Map;
56 56

57 57
import cn.jpush.android.api.JPushInterface;
58 58
import okhttp3.Call;
59
import okhttp3.OkHttpClient;
60 59

61 60

62 61
public class MainApplication extends MultiDexApplication {
@ -142,7 +141,7 @@ public class MainApplication extends MultiDexApplication {
142 141
    public static Double search_jing = 0.0, search_wei = 0.0;
143 142
    public static Context context;
144 143
    public static String current_code = "3.5";
145
    public static String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "cdz_android";
144
    public static String storePath = "";
146 145
    public static String q_content = "";
147 146
    public static Map<String, String> q_map = new HashMap<>();
148 147
    public static boolean isAppStart;
@ -156,6 +155,7 @@ public class MainApplication extends MultiDexApplication {
156 155
    public void onCreate() {
157 156
        super.onCreate();
158 157
        this.context = getApplicationContext();
158
        storePath = PhotoUtils.CACHE_DIR;
159 159
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
160 160
        StrictMode.setVmPolicy(builder.build());
161 161
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {

+ 0 - 23
app/src/main/java/com/electric/chargingpile/fragment/YueFragment.java

@ -1,23 +0,0 @@
1
package com.electric.chargingpile.fragment;
2
3
import android.os.Bundle;
4
import androidx.fragment.app.Fragment;
5
import android.view.LayoutInflater;
6
import android.view.View;
7
import android.view.ViewGroup;
8
9
import com.electric.chargingpile.R;
10
11
public class YueFragment extends Fragment {
12
13
14
    @Override
15
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
16
                             Bundle savedInstanceState) {
17
        // Inflate the layout for this fragment
18
        View view = inflater.inflate(R.layout.fragment_yue, null);
19
        return view;
20
    }
21
22
23
}

+ 0 - 304
app/src/main/java/com/electric/chargingpile/fragment/ZoomingPhotoTextFragment.java

@ -1,304 +0,0 @@
1
package com.electric.chargingpile.fragment;
2
3
import android.graphics.Bitmap;
4
import android.os.Bundle;
5
import android.os.Environment;
6
import android.provider.MediaStore;
7
import androidx.fragment.app.Fragment;
8
import androidx.fragment.app.FragmentManager;
9
import androidx.fragment.app.FragmentStatePagerAdapter;
10
import androidx.viewpager.widget.ViewPager.OnPageChangeListener;
11
import android.text.TextUtils;
12
import android.view.LayoutInflater;
13
import android.view.View;
14
import android.view.ViewGroup;
15
import android.widget.LinearLayout;
16
import android.widget.RelativeLayout;
17
import android.widget.ScrollView;
18
import android.widget.TextView;
19
import android.widget.Toast;
20
21
import com.electric.chargingpile.R;
22
import com.electric.chargingpile.application.MainApplication;
23
import com.electric.chargingpile.data.TopicDetailBean;
24
import com.electric.chargingpile.iview.RecyclerItemClickListener;
25
import com.electric.chargingpile.util.JsonUtils;
26
import com.electric.chargingpile.util.ToastUtil;
27
import com.electric.chargingpile.widge.photoview.PhotoView;
28
import com.electric.chargingpile.widge.photoview.PhotoViewAttacher;
29
import com.electric.chargingpile.widge.photoview.ZoomingViewpager;
30
import com.zhy.http.okhttp.OkHttpUtils;
31
import com.zhy.http.okhttp.callback.StringCallback;
32
33
import java.io.File;
34
import java.io.FileNotFoundException;
35
import java.io.FileOutputStream;
36
import java.io.IOException;
37
import java.util.ArrayList;
38
import java.util.HashMap;
39
import java.util.Map;
40
41
import cn.sharesdk.framework.Platform;
42
import cn.sharesdk.framework.PlatformActionListener;
43
import okhttp3.Call;
44
45
public class ZoomingPhotoTextFragment extends Fragment implements PhotoViewAttacher.OnPhotoTapListener, View.OnClickListener, PlatformActionListener {
46
47
    int position = 0, index = 0;
48
    private RelativeLayout app_activity_redmandetail_title_left_layout;
49
    private TextView act_zomming_current_pic_data, act_zomming_current_pic_all;
50
    private ZoomingViewpager photoPager;
51
    LinearLayout act_zomming_dot;
52
    ImageScanAdapter samplePagerAdapter;
53
54
    private RelativeLayout act_photo_content_view, act_zomming_bottom_comment, act_zomming_bottom_layout;
55
    ScrollView act_photo_content_vieww;
56
57
    public ArrayList<String> photoArrayList = new ArrayList<>();
58
59
    private String targetId, targetType;
60
    View view;
61
62
    @Override
63
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
64
65
        view = inflater.inflate(R.layout.activity_zoom_car_photo, null, false);
66
        initView();
67
        return view;
68
    }
69
70
    protected void initView() {
71
72
        act_zomming_current_pic_all = (TextView) view.findViewById(R.id.act_zomming_current_pic_all);
73
        view.findViewById(R.id.app_activity_redmandetail_title_back_layout).setOnClickListener(this);
74
//        act_photo_content = (TextView) findViewById(R.id.act_photo_content);
75
        act_photo_content_view = (RelativeLayout) view.findViewById(R.id.act_photo_content_view);
76
        act_zomming_bottom_comment = (RelativeLayout) view.findViewById(R.id.act_zomming_bottom_comment);
77
        act_zomming_bottom_layout = (RelativeLayout) view.findViewById(R.id.act_zomming_bottom_layout);
78
        act_photo_content_vieww = (ScrollView) view.findViewById(R.id.act_photo_content_vieww);
79
        app_activity_redmandetail_title_left_layout = (RelativeLayout) view.findViewById(R.id
80
                .app_activity_redmandetail_title_left_layout);
81
        act_zomming_current_pic_data = (TextView) view.findViewById(R.id.act_zomming_current_pic_data);
82
83
        targetId = "7";
84
        targetType = "24";
85
        requestServer();
86
    }
87
88
    private void requestServer() {
89
        String url = MainApplication.urlNew + "/topic/detail.do";
90
        Map<String, String> map = new HashMap<>();
91
        map.put("targetId", targetId);
92
        map.put("targetType", targetType);
93
        map.put("limit", "3");
94
        OkHttpUtils.get().params(map).url(url).build().connTimeOut(6000).readTimeOut(6000).execute(new StringCallback() {
95
            @Override
96
            public void onError(Call call, Exception e) {
97
                ToastUtil.showToast(getActivity(), "加载失败,请重试", Toast.LENGTH_SHORT);
98
            }
99
100
            @Override
101
            public void onResponse(String response) {
102
                String rtnCode = JsonUtils.getKeyResult(response, "code");
103
                if ("1000".equals(rtnCode)) {
104
                    String rtnMsg = JsonUtils.getKeyResult(response, "data");
105
                    ArrayList<TopicDetailBean> topicDetailBeans = (ArrayList<TopicDetailBean>) JsonUtils.parseToObjectList(rtnMsg, TopicDetailBean.class);
106
                    setData(topicDetailBeans);
107
                }
108
            }
109
        });
110
    }
111
112
    private void setData(ArrayList<TopicDetailBean> topicDetailBeans) {
113
        position = 0;
114
        for (int i = 0; i < topicDetailBeans.size(); i++) {
115
            photoArrayList.add(topicDetailBeans.get(i).coverImgUrl);
116
        }
117
        act_zomming_current_pic_all.setText("/" + photoArrayList.size());
118
        initLayoutView();
119
        index = position;
120
        draw_Point(position);
121
    }
122
123
    /**
124
     * 绘制游标背景
125
     */
126
    int askFlg;
127
    String subsidyPrice;
128
129
    public void draw_Point(int index) {
130
        act_zomming_current_pic_data.setText((index + 1) + "");
131
    }
132
133
134
    private void initLayoutView() {
135
        act_zomming_dot = (LinearLayout) view.findViewById(R.id.act_zomming_dot);
136
        photoPager = (ZoomingViewpager) view.findViewById(R.id.act_zoomingphoto_photo);
137
        samplePagerAdapter = new ImageScanAdapter(getActivity().getSupportFragmentManager(), photoArrayList);
138
        photoPager.setAdapter(samplePagerAdapter);
139
        photoPager.setCurrentItem(position);
140
141
        photoPager.addOnPageChangeListener(new OnPageChangeListener() {
142
143
            @Override
144
            public void onPageSelected(int arg0) {
145
                index = arg0;
146
                draw_Point(arg0);
147
            }
148
149
            @Override
150
            public void onPageScrolled(int arg0, float arg1, int arg2) {
151
                // TODO Auto-generated method stub
152
153
            }
154
155
            @Override
156
            public void onPageScrollStateChanged(int arg0) {
157
                // TODO Auto-generated method stub
158
159
            }
160
        });
161
    }
162
163
    PhotoViewAttacher mAttacher;
164
    PhotoView photoView;
165
166
    /**
167
     * A callback to receive where the user taps on a photo. You will only
168
     * receive a callback if the user taps on the actual photo, tapping on
169
     * 'whitespace' will be ignored.
170
     *
171
     * @param view - View the user tapped.
172
     * @param x    - where the user tapped from the of the Drawable, as
173
     *             percentage of the Drawable width.
174
     * @param y    - where the user tapped from the top of the Drawable, as
175
     */
176
    @Override
177
    public void onPhotoTap(View view, float x, float y) {
178
        if (app_activity_redmandetail_title_left_layout.getVisibility() == View.VISIBLE) {
179
            app_activity_redmandetail_title_left_layout.setVisibility(View.GONE);
180
            act_photo_content_vieww.setVisibility(View.GONE);
181
            act_photo_content_view.setVisibility(View.GONE);
182
//            pdv.setVisibility(View.GONE);
183
            act_zomming_bottom_comment.setVisibility(View.GONE);
184
185
            act_zomming_bottom_layout.setVisibility(View.VISIBLE);
186
        } else {
187
            app_activity_redmandetail_title_left_layout.setVisibility(View.VISIBLE);
188
            act_photo_content_vieww.setVisibility(View.VISIBLE);
189
            act_photo_content_view.setVisibility(View.VISIBLE);
190
            act_zomming_bottom_comment.setVisibility(View.VISIBLE);
191
            act_zomming_bottom_layout.setVisibility(View.GONE);
192
        }
193
        // finish();
194
    }
195
196
    public void saveBitmap(String picName, Bitmap bm) {
197
        if (bm != null) {
198
            String result = "";
199
            String folder = Environment.getExternalStorageDirectory().getAbsoluteFile() + File.separator + "touch/img/";
200
            File folderFile = new File(folder);
201
            try {
202
                if (!folderFile.exists()) {
203
                    folderFile.mkdirs();
204
                }
205
                File f = new File(folder, picName);
206
                if (!f.exists()) {
207
                    f.createNewFile();
208
                }
209
210
                FileOutputStream out = new FileOutputStream(f);
211
                bm.compress(Bitmap.CompressFormat.PNG, 90, out);
212
                out.flush();
213
                out.close();
214
                result = "success_sd";
215
                // 其次把文件插入到系统图库
216
                MediaStore.Images.Media.insertImage(getActivity().getBaseContext().getContentResolver(),
217
                        f.getAbsolutePath(), picName, null);
218
                result = "success";
219
            } catch (FileNotFoundException e) {
220
                // TODO Auto-generated catch block
221
                e.printStackTrace();
222
                result = "fail";
223
            } catch (IOException e) {
224
                // TODO Auto-generated catch block
225
                e.printStackTrace();
226
                result = "fail";
227
            }
228
//            bm.recycle();
229
//            bm = null;
230
            if ("success".equals(result)) {
231
                Toast.makeText(getActivity(), "已成功保存到相册", Toast.LENGTH_SHORT).show();
232
            } else if ("success_sd".equals(result)) {
233
                Toast.makeText(getActivity(), "已成功保存到内存卡", Toast.LENGTH_SHORT).show();
234
            } else {
235
                Toast.makeText(getActivity(), "保存失败", Toast.LENGTH_SHORT).show();
236
            }
237
        }
238
    }
239
240
    @Override
241
    public void onClick(View v) {
242
        switch (v.getId()) {
243
        }
244
    }
245
246
    @Override
247
    public void onComplete(Platform platform, int i, HashMap<String, Object> hashMap) {
248
        Toast.makeText(getActivity(), platform.getName(), Toast.LENGTH_SHORT).show();
249
    }
250
251
    @Override
252
    public void onError(Platform platform, int i, Throwable throwable) {
253
        Toast.makeText(getActivity(), platform.getName(), Toast.LENGTH_SHORT).show();
254
    }
255
256
    @Override
257
    public void onCancel(Platform platform, int i) {
258
        Toast.makeText(getActivity(), platform.getName(), Toast.LENGTH_SHORT).show();
259
    }
260
261
    class ImageScanAdapter extends FragmentStatePagerAdapter {
262
263
        private ArrayList<String> picData;
264
265
        public ImageScanAdapter(FragmentManager fm, ArrayList<String> picData) {
266
            super(fm);
267
            this.picData = picData;
268
        }
269
270
        @Override
271
        public Fragment getItem(int arg0) {
272
            String picUrl = picData.get(arg0);
273
            Bundle b = new Bundle();
274
            if (!TextUtils.isEmpty(picUrl)) {
275
                b.putString("url", picUrl);
276
            }
277
278
            ImageScanTextFragment f = new ImageScanTextFragment();
279
            f.setArguments(b);
280
            return f;
281
        }
282
283
        @Override
284
        public int getCount() {
285
            return picData.size();
286
        }
287
288
    }
289
290
    private class MainAdapterItemClickListener implements RecyclerItemClickListener {
291
        public void onItemClickListener(int index) {
292
            position = 0;
293
//            for (int i = 0; i < index; i++) {
294
//                for (int j = 0; j < picsVos.get(i).picsBeanList.size(); j++) {
295
//                    position++;
296
//                }
297
//            }
298
            draw_Point(position);
299
            photoPager.setCurrentItem(position);
300
//            }
301
302
        }
303
    }
304
}

+ 152 - 0
app/src/main/java/com/electric/chargingpile/util/DownloadUtil.java

@ -0,0 +1,152 @@
1
package com.electric.chargingpile.util;
2
3
import android.content.Context;
4
5
import android.util.Log;
6
7
import androidx.annotation.NonNull;
8
9
10
import java.io.File;
11
import java.io.FileOutputStream;
12
import java.io.IOException;
13
import java.io.InputStream;
14
import java.util.concurrent.TimeUnit;
15
16
import okhttp3.Call;
17
import okhttp3.Callback;
18
import okhttp3.OkHttpClient;
19
import okhttp3.Request;
20
import okhttp3.Response;
21
22
public class DownloadUtil {
23
 
24
    private static DownloadUtil downloadUtil;
25
    private final OkHttpClient okHttpClient;
26
    private Context context;
27
    private String TAG = "下载页面";
28
 
29
    public static DownloadUtil getInstance() {
30
        if (downloadUtil == null) {
31
            downloadUtil = new DownloadUtil();
32
        }
33
        return downloadUtil;
34
    }
35
 
36
    private DownloadUtil() {
37
        okHttpClient = new OkHttpClient.Builder()
38
                .readTimeout(20, TimeUnit.MINUTES)
39
                .writeTimeout(20, TimeUnit.MINUTES)
40
                .connectTimeout(20, TimeUnit.MINUTES)
41
                .build();
42
    }
43
 
44
    /**
45
     * @param url 下载连接
46
     * @param saveDir 储存下载文件的SDCard目录
47
     * @param listener 下载监听
48
     */
49
    public void download(Context context, final String url, final String saveDir,final String fileName, final OnDownloadListener listener) {
50
        this.context= context;
51
        // 需要token的时候可以这样做
52
        // SharedPreferences sp=MyApp.getAppContext().getSharedPreferences("loginInfo", MODE_PRIVATE);
53
        // Request request = new Request.Builder().header("token",sp.getString("token" , "")).url(url).build();
54
 
55
        Request request = new Request.Builder().url(url)
56
                .build();
57
        
58
        okHttpClient.newCall(request).enqueue(new Callback() {
59
            @Override
60
            public void onFailure(Call call, IOException e) {
61
                // 下载失败
62
                listener.onDownloadFailed(e);
63
            }
64
            @Override
65
            public void onResponse(Call call, Response response) throws IOException {
66
                InputStream is = null;
67
                byte[] buf = new byte[2048];
68
                int len = 0;
69
                FileOutputStream fos = null;
70
                // 储存下载文件的目录
71
                String savePath = isExistDir(saveDir);
72
                Log.w(TAG,"存储下载目录:"+savePath);
73
                try {
74
                    is = response.body().byteStream();
75
                    long total = response.body().contentLength();
76
                    File file = new File(savePath, getNameFromUrl(fileName));
77
                    Log.w(TAG,"最终路径:"+file);
78
                    fos = new FileOutputStream(file);
79
                    long sum = 0;
80
                    while ((len = is.read(buf)) != -1) {
81
                        fos.write(buf, 0, len);
82
                        sum += len;
83
                        int progress = (int) (sum * 1.0f / total * 100);
84
                        // 下载中
85
                        listener.onDownloading(progress);
86
                    }
87
                    fos.flush();
88
                    // 下载完成
89
                    listener.onDownloadSuccess(file);
90
                } catch (Exception e) {
91
                    listener.onDownloadFailed(e);
92
                } finally {
93
                    try {
94
                        if (is != null)
95
                            is.close();
96
                    } catch (IOException e) {
97
                    }
98
                    try {
99
                        if (fos != null)
100
                            fos.close();
101
                    } catch (IOException e) {
102
                    }
103
                }
104
            }
105
        });
106
    }
107
 
108
    /**
109
     * @param saveDir
110
     * @return
111
     * @throws IOException
112
     * 判断下载目录是否存在
113
     */
114
    private String isExistDir(String saveDir) throws IOException {
115
        // 下载位置
116
        File downloadFile = new File(saveDir);
117
        if (!downloadFile.mkdirs()) {
118
            downloadFile.createNewFile();
119
        }
120
        String savePath = downloadFile.getAbsolutePath();
121
        Log.w(TAG,"下载目录:"+savePath);
122
        return savePath;
123
    }
124
 
125
    /**
126
     * @param url
127
     * @return
128
     * 传入文件名
129
     */
130
    @NonNull
131
    public String getNameFromUrl(String url) {
132
        return url;
133
    }
134
 
135
    public interface OnDownloadListener {
136
        /**
137
         * 下载成功
138
         */
139
        void onDownloadSuccess(File file);
140
 
141
        /**
142
         * @param progress
143
         * 下载进度
144
         */
145
        void onDownloading(int progress);
146
 
147
        /**
148
         * 下载失败
149
         */
150
        void onDownloadFailed(Exception e);
151
    }
152
}

+ 0 - 32
app/src/main/java/com/electric/chargingpile/util/ImageTools.java

@ -252,37 +252,5 @@ public final class ImageTools {
252 252
        }
253 253
    }
254 254
255
    public static boolean saveImageToGallery(Context context, Bitmap bmp, String photoName) {
256
        // 首先保存图片
257
        String storePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "cdz_android";
258
        File appDir = new File(storePath);
259
        if (!appDir.exists()) {
260
            appDir.mkdir();
261
        }
262
        String fileName = photoName + ".png";
263
        File file = new File(appDir, fileName);
264
        try {
265
            FileOutputStream fos = new FileOutputStream(file);
266
            //通过io流的方式来压缩保存图片
267
            boolean isSuccess = bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
268
            fos.flush();
269
            fos.close();
270
271
            //把文件插入到系统图库
272
            //MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), fileName, null);
273
274
            //保存图片后发送广播通知更新数据库
275
            Uri uri = Uri.fromFile(file);
276
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
277
            if (isSuccess) {
278
                return true;
279
            } else {
280
                return false;
281
            }
282
        } catch (IOException e) {
283
            e.printStackTrace();
284
        }
285
        return false;
286
    }
287 255
288 256
}

+ 82 - 0
app/src/main/java/com/electric/chargingpile/util/PhotoUtils.java

@ -6,7 +6,9 @@ package com.electric.chargingpile.util;
6 6
7 7
import android.annotation.SuppressLint;
8 8
import android.app.Activity;
9
import android.content.ContentResolver;
9 10
import android.content.ContentUris;
11
import android.content.ContentValues;
10 12
import android.content.Context;
11 13
import android.content.Intent;
12 14
import android.database.Cursor;
@ -16,8 +18,20 @@ import android.os.Build;
16 18
import android.os.Environment;
17 19
import android.provider.DocumentsContract;
18 20
import android.provider.MediaStore;
21
import android.widget.Toast;
22
23
import androidx.core.content.FileProvider;
19 24
import androidx.fragment.app.Fragment;
20 25
26
import com.electric.chargingpile.activity.AboutActivity;
27
import com.electric.chargingpile.application.MainApplication;
28
29
import java.io.File;
30
import java.io.FileNotFoundException;
31
import java.io.FileOutputStream;
32
import java.io.IOException;
33
import java.io.OutputStream;
34
21 35
/**
22 36
 * 相片工具类
23 37
 */
@ -283,5 +297,73 @@ public class PhotoUtils {
283 297
        return "com.android.providers.media.documents".equals(uri.getAuthority());
284 298
    }
285 299
300
   public static String CACHE_DIR = MainApplication.context.getExternalCacheDir() + File.separator + "cdz/";
301
   public static String DOWNLOADS = MainApplication.context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + File.separator + "cdz/";
302
303
304
    public static void saveBitmap(Context context,Bitmap mBitmap,String filePath,String fileName) {
305
        File directory = new File(filePath);
306
        File f = new File(directory, fileName);
307
        try {
308
            if (!directory.exists()) {
309
                directory.mkdir();//没有目录先创建目录
310
            }
311
            f.createNewFile();
312
        } catch (IOException e) {
313
            // TODO Auto-generated catch block
314
        }
315
        FileOutputStream fOut = null;
316
        try {
317
            fOut = new FileOutputStream(f);
318
        } catch (Exception e) {
319
            e.printStackTrace();
320
        }
321
        mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
322
        Toast.makeText(context, "保存成功", Toast.LENGTH_SHORT).show();
323
        try {
324
            fOut.flush();
325
        } catch (IOException e) {
326
            e.printStackTrace();
327
        }
328
        try {
329
            fOut.close();
330
        } catch (IOException e) {
331
            e.printStackTrace();
332
        }
333
        ContentResolver contentResolver = MainApplication.context.getContentResolver();
334
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
335
            Uri insert = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
336
            try {
337
                OutputStream outputStream =  contentResolver.openOutputStream(insert);
338
                if (outputStream!=null){
339
                    mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
340
                }
341
            } catch (FileNotFoundException e) {
342
                e.printStackTrace();
343
            }
344
345
        }else{
346
            MediaStore.Images.Media.insertImage(contentResolver, mBitmap, "", "");
347
            Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
348
            Uri uri = parseUri(new File(CACHE_DIR));
349
            intent.setData(uri);
350
            context.sendBroadcast(intent);
351
        }
352
    }
353
    public static void saveBitmap(Context context,Bitmap mBitmap) {
354
        saveBitmap(context,mBitmap,CACHE_DIR,System.currentTimeMillis()+".jpeg");
355
    }
356
    public static Uri parseUri(File cameraFile) {
357
        Uri imageUri;
358
        String authority = MainApplication.context.getPackageName() + ".provider";
359
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
360
            //通过FileProvider创建一个content类型的Uri
361
            imageUri = FileProvider.getUriForFile(MainApplication.context, authority, cameraFile);
362
        } else {
363
            imageUri = Uri.fromFile(cameraFile);
364
        }
365
        return imageUri;
366
    }
367
286 368
}
287 369

+ 1 - 0
app/src/main/res/xml/provider_paths.xml

@ -2,4 +2,5 @@
2 2
<paths xmlns:android="http://schemas.android.com/apk/res/android">
3 3
    <!--"."表示所有路径-->
4 4
    <external-path name="external_files" path="."/>
5
    <root-path path="" name="rc_root_path"/>
5 6
</paths>

add ijkplayer library · 704d721c80 - Gogs: Go Git Service
浏览代码

add ijkplayer library

1145873331@qq.com 7 年之前
父节点
当前提交
704d721c80
共有 54 个文件被更改,包括 5865 次插入48 次删除
  1. 二进制
      app/libs/armeabi/libijkffmpeg.so
  2. 二进制
      app/libs/armeabi/libijkplayer.so
  3. 二进制
      app/libs/armeabi/libijksdl.so
  4. 70 0
      app/src/main/java/com/electric/chargingpile/view/IRenderView.java
  5. 199 0
      app/src/main/java/com/electric/chargingpile/view/MeasureHelper.java
  6. 60 0
      app/src/main/java/com/electric/chargingpile/view/MediaPlayerCompat.java
  7. 238 0
      app/src/main/java/com/electric/chargingpile/view/TextureRenderView.java
  8. 1215 0
      app/src/main/java/com/electric/chargingpile/view/UpVideoView2.java
  9. 二进制
      app/src/main/res/drawable-xxhdpi/icon_at.png
  10. 二进制
      app/src/main/res/drawable-xxhdpi/icon_back.png
  11. 二进制
      app/src/main/res/drawable-xxhdpi/icon_close.png
  12. 二进制
      app/src/main/res/drawable-xxhdpi/icon_comment.png
  13. 二进制
      app/src/main/res/drawable-xxhdpi/icon_expend.png
  14. 二进制
      app/src/main/res/drawable-xxhdpi/icon_forward.png
  15. 二进制
      app/src/main/res/drawable-xxhdpi/icon_likeed.png
  16. 二进制
      app/src/main/res/drawable-xxhdpi/icon_more.png
  17. 二进制
      app/src/main/res/drawable-xxhdpi/icon_write_comment.png
  18. 5 5
      app/src/main/res/layout/activity_videodetails.xml
  19. 2 2
      app/src/main/res/layout/sv_video_publish_info.xml
  20. 32 35
      app/src/main/res/layout/view_show_bottom.xml
  21. 5 6
      app/src/main/res/layout/view_show_comment.xml
  22. 1 0
      ijkplayer-java/.gitignore
  23. 21 0
      ijkplayer-java/build.gradle
  24. 3 0
      ijkplayer-java/gradle.properties
  25. 17 0
      ijkplayer-java/proguard-rules.pro
  26. 13 0
      ijkplayer-java/src/androidTest/java/tv/danmaku/ijk/media/player/ApplicationTest.java
  27. 4 0
      ijkplayer-java/src/main/AndroidManifest.xml
  28. 109 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java
  29. 418 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java
  30. 200 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java
  31. 27 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java
  32. 23 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java
  33. 22 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java
  34. 293 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java
  35. 380 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaMeta.java
  36. 1212 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java
  37. 29 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java
  38. 323 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java
  39. 99 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java
  40. 31 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java
  41. 35 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java
  42. 21 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java
  43. 5 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java
  44. 62 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java
  45. 108 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java
  46. 28 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java
  47. 30 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java
  48. 34 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java
  49. 209 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java
  50. 96 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java
  51. 142 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java
  52. 23 0
      ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java
  53. 15 0
      ijkplayer-java/src/main/project.properties
  54. 6 0
      ijkplayer-java/src/main/res/values/strings.xml

二进制
app/libs/armeabi/libijkffmpeg.so


二进制
app/libs/armeabi/libijkplayer.so


二进制
app/libs/armeabi/libijksdl.so


+ 70 - 0
app/src/main/java/com/electric/chargingpile/view/IRenderView.java

@ -0,0 +1,70 @@
1
package com.electric.chargingpile.view;
2
3
import android.graphics.SurfaceTexture;
4
import android.support.annotation.NonNull;
5
import android.support.annotation.Nullable;
6
import android.view.Surface;
7
import android.view.SurfaceHolder;
8
import android.view.View;
9
10
import tv.danmaku.ijk.media.player.IMediaPlayer;
11
12
public interface IRenderView {
13
    static final int AR_ASPECT_FIT_PARENT = 0; // without clip
14
    static final int AR_ASPECT_FILL_PARENT = 1; // may clip
15
    static final int AR_ASPECT_WRAP_CONTENT = 2;
16
    static final int AR_MATCH_PARENT = 3;
17
    static final int AR_16_9_FIT_PARENT = 4;
18
    static final int AR_4_3_FIT_PARENT = 5;
19
20
    View getView();
21
22
    boolean shouldWaitForResize();
23
24
    void setVideoSize(int videoWidth, int videoHeight);
25
26
    void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen);
27
28
    void setVideoRotation(int degree);
29
30
    void setAspectRatio(int aspectRatio);
31
32
    void addRenderCallback(@NonNull IRenderCallback callback);
33
34
    void removeRenderCallback(@NonNull IRenderCallback callback);
35
36
    interface ISurfaceHolder {
37
        void bindToMediaPlayer(IMediaPlayer mp);
38
39
        @NonNull
40
        IRenderView getRenderView();
41
42
        @Nullable
43
        SurfaceHolder getSurfaceHolder();
44
45
        @Nullable
46
        Surface openSurface();
47
48
        @Nullable
49
        SurfaceTexture getSurfaceTexture();
50
    }
51
52
    public interface IRenderCallback {
53
        /**
54
         * @param holder
55
         * @param width  could be 0
56
         * @param height could be 0
57
         */
58
        void onSurfaceCreated(@NonNull ISurfaceHolder holder, int width, int height);
59
60
        /**
61
         * @param holder
62
         * @param format could be 0
63
         * @param width
64
         * @param height
65
         */
66
        void onSurfaceChanged(@NonNull ISurfaceHolder holder, int format, int width, int height);
67
68
        void onSurfaceDestroyed(@NonNull ISurfaceHolder holder);
69
    }
70
}

+ 199 - 0
app/src/main/java/com/electric/chargingpile/view/MeasureHelper.java

@ -0,0 +1,199 @@
1
package com.electric.chargingpile.view;
2
3
4
import android.view.View;
5
6
import java.lang.ref.WeakReference;
7
8
public final class MeasureHelper {
9
    private WeakReference<View> mWeakView;
10
11
    private int mVideoWidth;
12
    private int mVideoHeight;
13
    private int mVideoSarNum;
14
    private int mVideoSarDen;
15
16
    private int mVideoRotationDegree;
17
18
    private int mMeasuredWidth;
19
    private int mMeasuredHeight;
20
21
    private int mCurrentAspectRatio = IRenderView.AR_ASPECT_FIT_PARENT;
22
23
    public MeasureHelper(View view) {
24
        mWeakView = new WeakReference<View>(view);
25
    }
26
27
    public View getView() {
28
        if (mWeakView == null)
29
            return null;
30
        return mWeakView.get();
31
    }
32
33
    public void setVideoSize(int videoWidth, int videoHeight) {
34
        mVideoWidth = videoWidth;
35
        mVideoHeight = videoHeight;
36
    }
37
38
    public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
39
        mVideoSarNum = videoSarNum;
40
        mVideoSarDen = videoSarDen;
41
    }
42
43
    public void setVideoRotation(int videoRotationDegree) {
44
        mVideoRotationDegree = videoRotationDegree;
45
    }
46
47
    /**
48
     * Must be called by View.onMeasure(int, int)
49
     *
50
     * @param widthMeasureSpec
51
     * @param heightMeasureSpec
52
     */
53
    public void doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
54
        //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
55
        //        + MeasureSpec.toString(heightMeasureSpec) + ")");
56
        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
57
            int tempSpec = widthMeasureSpec;
58
            widthMeasureSpec = heightMeasureSpec;
59
            heightMeasureSpec = tempSpec;
60
        }
61
62
        int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec);
63
        int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec);
64
        if (mCurrentAspectRatio == IRenderView.AR_MATCH_PARENT) {
65
            width = widthMeasureSpec;
66
            height = heightMeasureSpec;
67
        } else if (mVideoWidth > 0 && mVideoHeight > 0) {
68
            int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
69
            int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
70
            int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
71
            int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
72
73
            if (widthSpecMode == View.MeasureSpec.AT_MOST && heightSpecMode == View.MeasureSpec.AT_MOST) {
74
                float specAspectRatio = (float) widthSpecSize / (float) heightSpecSize;
75
                float displayAspectRatio;
76
                switch (mCurrentAspectRatio) {
77
                    case IRenderView.AR_16_9_FIT_PARENT:
78
                        displayAspectRatio = 16.0f / 9.0f;
79
                        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
80
                            displayAspectRatio = 1.0f / displayAspectRatio;
81
                        break;
82
                    case IRenderView.AR_4_3_FIT_PARENT:
83
                        displayAspectRatio = 4.0f / 3.0f;
84
                        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270)
85
                            displayAspectRatio = 1.0f / displayAspectRatio;
86
                        break;
87
                    case IRenderView.AR_ASPECT_FIT_PARENT:
88
                    case IRenderView.AR_ASPECT_FILL_PARENT:
89
                    case IRenderView.AR_ASPECT_WRAP_CONTENT:
90
                    default:
91
                        displayAspectRatio = (float) mVideoWidth / (float) mVideoHeight;
92
                        if (mVideoSarNum > 0 && mVideoSarDen > 0)
93
                            displayAspectRatio = displayAspectRatio * mVideoSarNum / mVideoSarDen;
94
                        break;
95
                }
96
                boolean shouldBeWider = displayAspectRatio > specAspectRatio;
97
98
                switch (mCurrentAspectRatio) {
99
                    case IRenderView.AR_ASPECT_FIT_PARENT:
100
                    case IRenderView.AR_16_9_FIT_PARENT:
101
                    case IRenderView.AR_4_3_FIT_PARENT:
102
                        if (shouldBeWider) {
103
                            // too wide, fix width
104
                            width = widthSpecSize;
105
                            height = (int) (width / displayAspectRatio);
106
                        } else {
107
                            // too high, fix height
108
                            height = heightSpecSize;
109
                            width = (int) (height * displayAspectRatio);
110
                        }
111
                        break;
112
                    case IRenderView.AR_ASPECT_FILL_PARENT:
113
                        if (shouldBeWider) {
114
                            // not high enough, fix height
115
                            height = heightSpecSize;
116
                            width = (int) (height * displayAspectRatio);
117
                        } else {
118
                            // not wide enough, fix width
119
                            width = widthSpecSize;
120
                            height = (int) (width / displayAspectRatio);
121
                        }
122
                        break;
123
                    case IRenderView.AR_ASPECT_WRAP_CONTENT:
124
                    default:
125
                        if (shouldBeWider) {
126
                            // too wide, fix width
127
                            width = Math.min(mVideoWidth, widthSpecSize);
128
                            height = (int) (width / displayAspectRatio);
129
                        } else {
130
                            // too high, fix height
131
                            height = Math.min(mVideoHeight, heightSpecSize);
132
                            width = (int) (height * displayAspectRatio);
133
                        }
134
                        break;
135
                }
136
            } else if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) {
137
                // the size is fixed
138
                width = widthSpecSize;
139
                height = heightSpecSize;
140
141
                // for compatibility, we adjust size based on aspect ratio
142
                if (mVideoWidth * height < width * mVideoHeight) {
143
                    //Log.i("@@@", "image too wide, correcting");
144
                    width = height * mVideoWidth / mVideoHeight;
145
                } else if (mVideoWidth * height > width * mVideoHeight) {
146
                    //Log.i("@@@", "image too tall, correcting");
147
                    height = width * mVideoHeight / mVideoWidth;
148
                }
149
            } else if (widthSpecMode == View.MeasureSpec.EXACTLY) {
150
                // only the width is fixed, adjust the height to match aspect ratio if possible
151
                width = widthSpecSize;
152
                height = width * mVideoHeight / mVideoWidth;
153
                if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
154
                    // couldn't match aspect ratio within the constraints
155
                    height = heightSpecSize;
156
                }
157
            } else if (heightSpecMode == View.MeasureSpec.EXACTLY) {
158
                // only the height is fixed, adjust the width to match aspect ratio if possible
159
                height = heightSpecSize;
160
                width = height * mVideoWidth / mVideoHeight;
161
                if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
162
                    // couldn't match aspect ratio within the constraints
163
                    width = widthSpecSize;
164
                }
165
            } else {
166
                // neither the width nor the height are fixed, try to use actual video size
167
                width = mVideoWidth;
168
                height = mVideoHeight;
169
                if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
170
                    // too tall, decrease both width and height
171
                    height = heightSpecSize;
172
                    width = height * mVideoWidth / mVideoHeight;
173
                }
174
                if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
175
                    // too wide, decrease both width and height
176
                    width = widthSpecSize;
177
                    height = width * mVideoHeight / mVideoWidth;
178
                }
179
            }
180
        } else {
181
            // no size yet, just adopt the given spec sizes
182
        }
183
184
        mMeasuredWidth = width;
185
        mMeasuredHeight = height;
186
    }
187
188
    public int getMeasuredWidth() {
189
        return mMeasuredWidth;
190
    }
191
192
    public int getMeasuredHeight() {
193
        return mMeasuredHeight;
194
    }
195
196
    public void setAspectRatio(int aspectRatio) {
197
        mCurrentAspectRatio = aspectRatio;
198
    }
199
}

+ 60 - 0
app/src/main/java/com/electric/chargingpile/view/MediaPlayerCompat.java

@ -0,0 +1,60 @@
1
package com.electric.chargingpile.view;
2
3
4
import tv.danmaku.ijk.media.player.IMediaPlayer;
5
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
6
import tv.danmaku.ijk.media.player.MediaPlayerProxy;
7
import tv.danmaku.ijk.media.player.TextureMediaPlayer;
8
9
public class MediaPlayerCompat {
10
    public static String getName(IMediaPlayer mp) {
11
        if (mp == null) {
12
            return "null";
13
        } else if (mp instanceof TextureMediaPlayer) {
14
            StringBuilder sb = new StringBuilder("TextureMediaPlayer <");
15
            IMediaPlayer internalMediaPlayer = ((TextureMediaPlayer) mp).getInternalMediaPlayer();
16
            if (internalMediaPlayer == null) {
17
                sb.append("null>");
18
            } else {
19
                sb.append(internalMediaPlayer.getClass().getSimpleName());
20
                sb.append(">");
21
            }
22
            return sb.toString();
23
        } else {
24
            return mp.getClass().getSimpleName();
25
        }
26
    }
27
28
    public static IjkMediaPlayer getIjkMediaPlayer(IMediaPlayer mp) {
29
        IjkMediaPlayer ijkMediaPlayer = null;
30
        if (mp == null) {
31
            return null;
32
        } if (mp instanceof IjkMediaPlayer) {
33
            ijkMediaPlayer = (IjkMediaPlayer) mp;
34
        } else if (mp instanceof MediaPlayerProxy && ((MediaPlayerProxy) mp).getInternalMediaPlayer() instanceof IjkMediaPlayer) {
35
            ijkMediaPlayer = (IjkMediaPlayer) ((MediaPlayerProxy) mp).getInternalMediaPlayer();
36
        }
37
        return ijkMediaPlayer;
38
    }
39
40
    public static void selectTrack(IMediaPlayer mp, int stream) {
41
        IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
42
        if (ijkMediaPlayer == null)
43
            return;
44
        ijkMediaPlayer.selectTrack(stream);
45
    }
46
47
    public static void deselectTrack(IMediaPlayer mp, int stream) {
48
        IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
49
        if (ijkMediaPlayer == null)
50
            return;
51
        ijkMediaPlayer.deselectTrack(stream);
52
    }
53
54
    public static int getSelectedTrack(IMediaPlayer mp, int trackType) {
55
        IjkMediaPlayer ijkMediaPlayer = getIjkMediaPlayer(mp);
56
        if (ijkMediaPlayer == null)
57
            return -1;
58
        return ijkMediaPlayer.getSelectedTrack(trackType);
59
    }
60
}

+ 238 - 0
app/src/main/java/com/electric/chargingpile/view/TextureRenderView.java

@ -0,0 +1,238 @@
1
package com.electric.chargingpile.view;
2
3
4
import android.content.Context;
5
import android.graphics.SurfaceTexture;
6
import android.os.Build;
7
import android.support.annotation.NonNull;
8
import android.support.annotation.Nullable;
9
import android.support.annotation.RequiresApi;
10
import android.util.AttributeSet;
11
import android.util.Log;
12
import android.view.Surface;
13
import android.view.SurfaceHolder;
14
import android.view.TextureView;
15
import android.view.View;
16
17
import java.lang.ref.WeakReference;
18
import java.util.Map;
19
import java.util.concurrent.ConcurrentHashMap;
20
21
import tv.danmaku.ijk.media.player.IMediaPlayer;
22
23
/**
24
 * Created by 27536 on 2017/9/27.
25
 */
26
27
@RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
28
public class TextureRenderView extends TextureView implements IRenderView {
29
30
    private MeasureHelper mMeasureHelper;
31
    private Listener mSurfaceTextureListener;
32
33
34
    public TextureRenderView(Context context) {
35
        super(context);
36
        initView(context);
37
    }
38
39
    public TextureRenderView(Context context, AttributeSet attrs) {
40
        super(context, attrs);
41
        initView(context);
42
    }
43
44
    public TextureRenderView(Context context, AttributeSet attrs, int defStyleAttr) {
45
        super(context, attrs, defStyleAttr);
46
        initView(context);
47
    }
48
49
    private void initView(Context context) {
50
        mSurfaceTextureListener = new Listener(this);
51
        mMeasureHelper = new MeasureHelper(this);
52
        setSurfaceTextureListener(mSurfaceTextureListener);
53
    }
54
55
    @Override
56
    public View getView() {
57
        return this;
58
    }
59
60
    @Override
61
    public boolean shouldWaitForResize() {
62
        return false;
63
    }
64
65
    @Override
66
    public void setVideoSize(int videoWidth, int videoHeight) {
67
        if (videoWidth > 0 && videoHeight > 0) {
68
            mMeasureHelper.setVideoSize(videoWidth, videoHeight);
69
            requestLayout();
70
        }
71
    }
72
73
    @Override
74
    public void setVideoSampleAspectRatio(int videoSarNum, int videoSarDen) {
75
        if (videoSarNum > 0 && videoSarDen > 0) {
76
            mMeasureHelper.setVideoSampleAspectRatio(videoSarNum, videoSarDen);
77
            requestLayout();
78
        }
79
    }
80
81
    @Override
82
    public void setVideoRotation(int degree) {
83
        if (degree != getRotation()) {
84
            Log.i("setVideoRotation", "degree:" + degree);
85
            mMeasureHelper.setVideoRotation(degree);
86
            super.setRotation(degree);
87
            requestLayout();
88
        }
89
    }
90
91
    @Override
92
    public void setAspectRatio(int aspectRatio) {
93
        mMeasureHelper.setAspectRatio(aspectRatio);
94
        requestLayout();
95
    }
96
97
    @Override
98
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
99
        mMeasureHelper.doMeasure(widthMeasureSpec, heightMeasureSpec);
100
        setMeasuredDimension(mMeasureHelper.getMeasuredWidth(), mMeasureHelper.getMeasuredHeight());
101
    }
102
103
    @Override
104
    public void addRenderCallback(@NonNull IRenderCallback callback) {
105
        mSurfaceTextureListener.addRenderCallback(callback);
106
    }
107
108
    @Override
109
    public void removeRenderCallback(@NonNull IRenderCallback callback) {
110
        mSurfaceTextureListener.removeRenderCallback(callback);
111
    }
112
113
114
    private static final class Listener implements SurfaceTextureListener {
115
        SurfaceTexture mSurfaceTexture;
116
        Surface mSurface;
117
        private int mWidth;
118
        private int mHeight;
119
120
        private Map<IRenderCallback, Object> mRenderCallbackMap = new ConcurrentHashMap<>();
121
        private WeakReference<TextureRenderView> mWeakSurfaceView;
122
123
        public Listener(@NonNull TextureRenderView view) {
124
            mWeakSurfaceView = new WeakReference<>(view);
125
        }
126
127
        @Override
128
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
129
            mWidth = 0;
130
            mHeight = 0;
131
            mSurfaceTexture = surface;
132
            mSurface = new Surface(surface);
133
134
            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceTexture, mSurface);
135
            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
136
                renderCallback.onSurfaceCreated(surfaceHolder, 0, 0);
137
            }
138
        }
139
140
        @Override
141
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
142
            mSurfaceTexture = surface;
143
            mWidth = width;
144
            mHeight = height;
145
146
            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceTexture, mSurface);
147
            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
148
                renderCallback.onSurfaceChanged(surfaceHolder, -1, width, height);
149
            }
150
        }
151
152
        @Override
153
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
154
            mSurfaceTexture.release();
155
            mSurfaceTexture = null;
156
            Surface s = mSurface;
157
            mSurface = null;
158
            s.release();
159
160
            ISurfaceHolder surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceTexture, mSurface);
161
            for (IRenderCallback renderCallback : mRenderCallbackMap.keySet()) {
162
                renderCallback.onSurfaceDestroyed(surfaceHolder);
163
            }
164
            return false;
165
        }
166
167
        @Override
168
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
169
170
        }
171
172
        public void addRenderCallback(@NonNull IRenderCallback callback) {
173
            mRenderCallbackMap.put(callback, callback);
174
175
            ISurfaceHolder surfaceHolder = null;
176
            if (mSurfaceTexture != null) {
177
                surfaceHolder = new InternalSurfaceHolder(mWeakSurfaceView.get(), mSurfaceTexture, mSurface);
178
                callback.onSurfaceCreated(surfaceHolder, mWidth, mHeight);
179
            }
180
181
        }
182
183
        public void removeRenderCallback(@NonNull IRenderCallback callback) {
184
            mRenderCallbackMap.remove(callback);
185
        }
186
    }
187
188
189
    private static final class InternalSurfaceHolder implements ISurfaceHolder {
190
        private TextureRenderView mRenderView;
191
        private SurfaceTexture mSurfaceTexture;
192
        private Surface mSurface;
193
194
        public InternalSurfaceHolder(@NonNull TextureRenderView surfaceView,
195
                                     @Nullable SurfaceTexture surfaceHolder,
196
                                     @Nullable Surface surface) {
197
            mRenderView = surfaceView;
198
            mSurfaceTexture = surfaceHolder;
199
            mSurface = surface;
200
        }
201
202
        @Override
203
        public void bindToMediaPlayer(IMediaPlayer mp) {
204
            if (mp != null) {
205
                Log.i("bindToMediaPlayer", "mSurface isValid" + mSurface.isValid());
206
                mp.setSurface(mSurface);
207
            }
208
        }
209
210
        @NonNull
211
        @Override
212
        public IRenderView getRenderView() {
213
            return mRenderView;
214
        }
215
216
        @Nullable
217
        @Override
218
        public SurfaceHolder getSurfaceHolder() {
219
            return null;
220
        }
221
222
        @Nullable
223
        @Override
224
        public SurfaceTexture getSurfaceTexture() {
225
            return mSurfaceTexture;
226
        }
227
228
        @Nullable
229
        @Override
230
        public Surface openSurface() {
231
            return mSurface;
232
        }
233
    }
234
235
236
237
238
}

+ 1215 - 0
app/src/main/java/com/electric/chargingpile/view/UpVideoView2.java

@ -0,0 +1,1215 @@
1
package com.electric.chargingpile.view;
2
3
import android.annotation.TargetApi;
4
import android.app.Activity;
5
import android.app.AlertDialog;
6
import android.content.Context;
7
import android.content.DialogInterface;
8
import android.content.pm.ActivityInfo;
9
import android.graphics.drawable.Drawable;
10
import android.media.AudioManager;
11
import android.media.MediaPlayer;
12
import android.net.Uri;
13
import android.os.Build;
14
import android.os.Bundle;
15
import android.support.annotation.NonNull;
16
import android.util.AttributeSet;
17
import android.util.Log;
18
import android.view.Gravity;
19
import android.view.KeyEvent;
20
import android.view.MotionEvent;
21
import android.view.View;
22
import android.view.ViewGroup;
23
import android.view.WindowManager;
24
import android.webkit.WebSettings;
25
import android.webkit.WebView;
26
import android.widget.FrameLayout;
27
import android.widget.MediaController;
28
import android.widget.TableLayout;
29
30
import java.io.IOException;
31
import java.util.HashMap;
32
import java.util.Map;
33
34
35
import tv.danmaku.ijk.media.player.IMediaPlayer;
36
import tv.danmaku.ijk.media.player.IjkMediaPlayer;
37
import tv.danmaku.ijk.media.player.misc.ITrackInfo;
38
39
40
public class UpVideoView2 extends FrameLayout implements MediaController.MediaPlayerControl {
41
    private String TAG = "UpVideoView2";
42
    // settable by the client
43
    private Uri mUri;
44
    private Map<String, String> mHeaders;
45
46
    // all possible internal states
47
    private static final int STATE_ERROR = -1;
48
    private static final int STATE_IDLE = 0;
49
    private static final int STATE_PREPARING = 1;
50
    private static final int STATE_PREPARED = 2;
51
    private static final int STATE_PLAYING = 3;
52
    private static final int STATE_PAUSED = 4;
53
    private static final int STATE_PLAYBACK_COMPLETED = 5;
54
55
    // mCurrentState is a VideoView object's current state.
56
    // mTargetState is the state that a method caller intends to reach.
57
    // For instance, regardless the VideoView object's current state,
58
    // calling pause() intends to bring the object to a target state
59
    // of STATE_PAUSED.
60
    private int mCurrentState = STATE_IDLE;
61
    private int mTargetState = STATE_IDLE;
62
63
    // All the stuff we need for playing and showing a video
64
    private IRenderView.ISurfaceHolder mSurfaceHolder = null;
65
    private IjkMediaPlayer mMediaPlayer = null;
66
    // private int         mAudioSession;
67
    private int mVideoWidth;
68
    private int mVideoHeight;
69
    private int mSurfaceWidth;
70
    private int mSurfaceHeight;
71
    private int mVideoRotationDegree;
72
    private MediaController mMediaController;
73
    private IMediaPlayer.OnCompletionListener mOnCompletionListener;
74
    private IMediaPlayer.OnPreparedListener mOnPreparedListener;
75
    private int mCurrentBufferPercentage;
76
    private IMediaPlayer.OnErrorListener mOnErrorListener;
77
    private IMediaPlayer.OnInfoListener mOnInfoListener;
78
    private IMediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener;
79
    private IjkMediaPlayer.OnNativeInvokeListener mOnNativeInvokeListener;
80
    private int mSeekWhenPrepared;  // recording the seek position while preparing
81
    private boolean mCanPause = true;
82
    private boolean mCanSeekBack = true;
83
    private boolean mCanSeekForward = true;
84
85
    private int bufferSize = -1;
86
    private boolean isAutoPlay = true;
87
88
    private static final int MSG_CACHE_DRU = 20160101;
89
90
    private static final int CACHE_WATER = 1 * 1000;
91
92
    private long mPrepareStartTime = 0;
93
    private long mPrepareEndTime = 0;
94
95
    private long mSeekStartTime = 0;
96
    private long mSeekEndTime = 0;
97
98
99
    // OnNativeInvokeListener what
100
    public static final int AVAPP_EVENT_WILL_HTTP_OPEN = 1; //AVAppHttpEvent
101
    public static final int AVAPP_EVENT_DID_HTTP_OPEN = 2; //AVAppHttpEvent
102
    public static final int AVAPP_EVENT_WILL_HTTP_SEEK = 3; //AVAppHttpEvent
103
    public static final int AVAPP_EVENT_DID_HTTP_SEEK = 4; //AVAppHttpEvent
104
105
    public static final int AVAPP_EVENT_ASYNC_STATISTIC = 0x11000; //AVAppAsyncStatistic
106
    public static final int AVAPP_EVENT_ASYNC_READ_SPEED = 0x11001; //AVAppAsyncReadSpeed
107
    public static final int AVAPP_EVENT_IO_TRAFFIC = 0x12204; //AVAppIOTraffic
108
109
    public static final int AVAPP_CTRL_WILL_TCP_OPEN = 0x20001; //AVAppTcpIOControl
110
    public static final int AVAPP_CTRL_DID_TCP_OPEN = 0x20002; //AVAppTcpIOControl
111
112
    public static final int AVAPP_CTRL_WILL_HTTP_OPEN = 0x20003; //AVAppIOControl
113
    public static final int AVAPP_CTRL_WILL_LIVE_OPEN = 0x20005; //AVAppIOControl
114
115
    public static final int AVAPP_CTRL_WILL_CONCAT_SEGMENT_OPEN = 0x20007; //AVAppIOControl
116
    // OnNativeInvokeListener bundle key
117
    public static final String AVAPP_EVENT_URL = "url";
118
    public static final String AVAPP_EVENT_ERROR = "error";
119
    public static final String AVAPP_EVENT_HTTP_CODE = "http_code";
120
121
122
//    private android.os.Handler mHandler = new android.os.Handler() {
123
//        @Override
124
//        public void handleMessage(Message msg) {
125
//            switch (msg.what) {
126
//                case MSG_CACHE_DRU:
127
//                    if (mMediaPlayer != null) {
128
//
129
//                        Log.e(TAG, "audio_cache_time:" + mMediaPlayer.getAudioCachedDuration() + "   audio_cache_size" + mMediaPlayer.getAudioCachedBytes() + "  video_cache_time:" + mMediaPlayer.getVideoCachedDuration() + "  video_cache_size:" + mMediaPlayer.getVideoDecodeFramesPerSecond());
130
//                        Log.e(TAG, "audio_cache_pac:" + mMediaPlayer.getAudioCachedPackets() + "  video_cache_pac:" + mMediaPlayer.getAudioCachedPackets());
131
//
132
//                        if (mMediaPlayer.getAudioCachedDuration() > CACHE_WATER || mMediaPlayer.getVideoCachedDuration() > CACHE_WATER)
133
//                            resume();
134
//                    }
135
//                    mHandler.removeMessages(MSG_CACHE_DRU);
136
//                    mHandler.sendEmptyMessageDelayed(MSG_CACHE_DRU, 500);
137
//            }
138
//        }
139
//    };
140
141
    /** Subtitle rendering widget overlaid on top of the video. */
142
    // private RenderingWidget mSubtitleWidget;
143
144
    /**
145
     * Listener for changes to subtitle data, used to redraw when needed.
146
     */
147
    // private RenderingWidget.OnChangedListener mSubtitlesChangedListener;
148
149
    private Context mAppContext;
150
    private IRenderView mRenderView;
151
    private int mVideoSarNum;
152
    private int mVideoSarDen;
153
154
    private boolean isFullState;
155
    private ViewGroup.LayoutParams mRawParams;
156
157
    //    private MonitorRecorder monitorRecorder;
158
    private float playSpeed = .0f;
159
160
    private long bufferTime;
161
    private long startbufferTime;
162
    private static int PURSUETIME = 10 * 1000;
163
    private boolean isAutoPursue = true;
164
165
    public boolean isAutoPursue() {
166
        return isAutoPursue;
167
    }
168
169
    public void setAutoPursue(boolean autoPursue) {
170
        isAutoPursue = autoPursue;
171
    }
172
173
    private String ua = null;// user agent
174
175
    public boolean isFullState() {
176
        return isFullState;
177
    }
178
179
    public UpVideoView2(Context context) {
180
        super(context);
181
        initVideoView(context);
182
    }
183
184
    public UpVideoView2(Context context, AttributeSet attrs) {
185
        super(context, attrs);
186
        initVideoView(context);
187
    }
188
189
    public UpVideoView2(Context context, AttributeSet attrs, int defStyleAttr) {
190
        super(context, attrs, defStyleAttr);
191
        initVideoView(context);
192
    }
193
194
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
195
    public UpVideoView2(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
196
        super(context, attrs, defStyleAttr, defStyleRes);
197
        initVideoView(context);
198
    }
199
200
    // REMOVED: onMeasure
201
    // REMOVED: onInitializeAccessibilityEvent
202
    // REMOVED: onInitializeAccessibilityNodeInfo
203
    // REMOVED: resolveAdjustedSize
204
205
    private void initVideoView(Context context) {
206
        mAppContext = context.getApplicationContext();
207
        TextureRenderView renderView = new TextureRenderView(getContext());
208
        setRenderView(renderView);
209
210
        mVideoWidth = 0;
211
        mVideoHeight = 0;
212
        // REMOVED: getHolder().addCallback(mSHCallback);
213
        // REMOVED: getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
214
        setFocusable(true);
215
        setFocusableInTouchMode(true);
216
        requestFocus();
217
        // REMOVED: mPendingSubtitleTracks = new Vector<Pair<InputStream, MediaFormat>>();
218
        mCurrentState = STATE_IDLE;
219
        mTargetState = STATE_IDLE;
220
221
//        monitorRecorder = new MonitorRecorder(mAppContext);
222
223
        // user agent
224
        WebView webview;
225
        webview = new WebView(context);
226
        webview.layout(0, 0, 0, 0);
227
        WebSettings settings = webview.getSettings();
228
        this.ua = settings.getUserAgentString();
229
    }
230
231
    public void setRenderView(IRenderView renderView) {
232
        if (mRenderView != null) {
233
            if (mMediaPlayer != null)
234
                mMediaPlayer.setSurface(null);
235
236
            View renderUIView = mRenderView.getView();
237
            mRenderView.removeRenderCallback(mSHCallback);
238
            mRenderView = null;
239
            removeView(renderUIView);
240
        }
241
242
        if (renderView == null)
243
            return;
244
245
        mRenderView = renderView;
246
        renderView.setAspectRatio(mCurrentAspectRatio);
247
        if (mVideoWidth > 0 && mVideoHeight > 0)
248
            renderView.setVideoSize(mVideoWidth, mVideoHeight);
249
        if (mVideoSarNum > 0 && mVideoSarDen > 0)
250
            renderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
251
252
        View renderUIView = mRenderView.getView();
253
        LayoutParams lp = new LayoutParams(
254
                LayoutParams.WRAP_CONTENT,
255
                LayoutParams.WRAP_CONTENT,
256
                Gravity.CENTER);
257
        renderUIView.setLayoutParams(lp);
258
        addView(renderUIView);
259
260
        mRenderView.addRenderCallback(mSHCallback);
261
        mRenderView.setVideoRotation(mVideoRotationDegree);
262
    }
263
264
    /**
265
     * Sets video path.
266
     *
267
     * @param path the path of the video.
268
     */
269
    public void setVideoPath(String path) {
270
        setVideoURI(Uri.parse(path));
271
    }
272
273
    /**
274
     * Sets video URI.
275
     *
276
     * @param uri the URI of the video.
277
     */
278
    public void setVideoURI(Uri uri) {
279
        setVideoURI(uri, null);
280
    }
281
282
    /**
283
     * Sets video URI using specific headers.
284
     *
285
     * @param uri     the URI of the video.
286
     * @param headers the headers for the URI request.
287
     *                Note that the cross domain redirection is allowed by default, but that can be
288
     *                changed with key/value pairs through the headers parameter with
289
     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
290
     *                to disallow or allow cross domain redirection.
291
     */
292
    private void setVideoURI(Uri uri, Map<String, String> headers) {
293
        mUri = uri;
294
295
        if (uri.toString().startsWith("http")) {
296
            if (headers == null) {
297
                headers = new HashMap<>();
298
            }
299
            headers.put("X-Accept-Video-Encoding", "h265");
300
        }
301
302
        mHeaders = headers;
303
        mSeekWhenPrepared = 0;
304
        openVideo();
305
        requestLayout();
306
        invalidate();
307
    }
308
309
    // REMOVED: addSubtitleSource
310
    // REMOVED: mPendingSubtitleTracks
311
312
    public void stopPlayback() {
313
        if (mMediaPlayer != null) {
314
            mMediaPlayer.stop();
315
            mMediaPlayer.release();
316
317
            mMediaPlayer = null;
318
            mCurrentState = STATE_IDLE;
319
            mTargetState = STATE_IDLE;
320
            AudioManager am = (AudioManager) mAppContext.getSystemService(Context.AUDIO_SERVICE);
321
            am.abandonAudioFocus(null);
322
        }
323
    }
324
325
    @TargetApi(Build.VERSION_CODES.M)
326
    private void openVideo() {
327
        Log.i(TAG, "openVideo");
328
        if (mUri == null || mSurfaceHolder == null) {
329
            Log.i(TAG, "openVideo return mSurfaceHolder == null:" + (mSurfaceHolder == null));
330
            // not ready for playback just yet, will try again later
331
            return;
332
        }
333
        Log.i(TAG, "openVideo start");
334
        // we shouldn't clear the target state, because somebody might have
335
        // called start() previously
336
        release(false);
337
338
        //开始播放时间
339
//        monitorRecorder.start();
340
//        monitorRecorder.setPlayUrl(mUri.toString());
341
342
//        mHandler.removeMessages(MSG_CACHE_DRU);
343
//        mHandler.sendEmptyMessageDelayed(MSG_CACHE_DRU, 500);
344
345
        AudioManager am = (AudioManager) mAppContext.getSystemService(Context.AUDIO_SERVICE);
346
        am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
347
348
        try {
349
            mMediaPlayer = new IjkMediaPlayer();
350
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
351
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
352
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
353
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);
354
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", isAutoPlay ? 1 : 0);
355
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 1024 * 400);
356
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
357
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 0);
358
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", "64000");
359
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec_mpeg4", 1);
360
            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "enable-accurate-seek", 1);
361
362
//            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
363
//            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);
364
365
//            mMediaPlayer.setLooping(true);
366
//            mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "sync", "ext");
367
//            mMediaPlayer.setSpeed(1.03f);
368
369
            if (bufferSize != -1) {
370
                mMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", bufferSize);
371
            }
372
373
            // TODO: create SubtitleController in MediaPlayer, but we need
374
            // a context for the subtitle renderers
375
            final Context context = getContext();
376
            // REMOVED: SubtitleController
377
378
            // REMOVED: mAudioSession
379
            mMediaPlayer.setOnPreparedListener(mPreparedListener);
380
            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
381
            mMediaPlayer.setOnCompletionListener(mCompletionListener);
382
            mMediaPlayer.setOnErrorListener(mErrorListener);
383
            mMediaPlayer.setOnNativeInvokeListener(mNativeInvokeListener);
384
            mMediaPlayer.setOnInfoListener(mInfoListener);
385
            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
386
            mCurrentBufferPercentage = 0;
387
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
388
                mMediaPlayer.setDataSource(mAppContext, mUri, mHeaders);
389
            } else {
390
                mMediaPlayer.setDataSource(mUri.toString());
391
            }
392
            bindSurfaceHolder(mMediaPlayer, mSurfaceHolder);
393
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
394
            mMediaPlayer.setScreenOnWhilePlaying(true);
395
            mPrepareStartTime = System.currentTimeMillis();
396
            mMediaPlayer.prepareAsync();
397
398
            if (playSpeed != .0f) {
399
                mMediaPlayer.setSpeed(playSpeed);
400
            }
401
402
            // REMOVED: mPendingSubtitleTracks
403
404
            // we don't set the target state here either, but preserve the
405
            // target state that was there before.
406
            mCurrentState = STATE_PREPARING;
407
            attachMediaController();
408
        } catch (IOException ex) {
409
            Log.w(TAG, "Unable to open content: " + mUri, ex);
410
            mCurrentState = STATE_ERROR;
411
            mTargetState = STATE_ERROR;
412
            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
413
            return;
414
        } catch (IllegalArgumentException ex) {
415
            Log.w(TAG, "Unable to open content: " + mUri, ex);
416
            mCurrentState = STATE_ERROR;
417
            mTargetState = STATE_ERROR;
418
            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
419
            return;
420
        } finally {
421
            // REMOVED: mPendingSubtitleTracks.clear();
422
        }
423
    }
424
425
    public void setMediaController(MediaController controller) {
426
        if (mMediaController != null) {
427
            mMediaController.hide();
428
        }
429
        mMediaController = controller;
430
        attachMediaController();
431
    }
432
433
    private void attachMediaController() {
434
        if (mMediaPlayer != null && mMediaController != null) {
435
            mMediaController.setMediaPlayer(this);
436
            View anchorView = this.getParent() instanceof View ?
437
                    (View) this.getParent() : this;
438
            mMediaController.setAnchorView(anchorView);
439
            mMediaController.setEnabled(isInPlaybackState());
440
        }
441
    }
442
443
    IMediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
444
            new IMediaPlayer.OnVideoSizeChangedListener() {
445
                public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sarNum, int sarDen) {
446
                    if (mOnVideoSizeChangedListener != null) {
447
                        mOnVideoSizeChangedListener.onVideoSizeChanged(mp, width, height, sarNum, sarDen);
448
                    }
449
                    mVideoWidth = mp.getVideoWidth();
450
                    mVideoHeight = mp.getVideoHeight();
451
                    mVideoSarNum = mp.getVideoSarNum();
452
                    mVideoSarDen = mp.getVideoSarDen();
453
                    if (mVideoWidth != 0 && mVideoHeight != 0) {
454
                        if (mRenderView != null) {
455
                            mRenderView.setVideoSize(mVideoWidth, mVideoHeight);
456
                            mRenderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
457
                        }
458
                        // REMOVED: getHolder().setFixedSize(mVideoWidth, mVideoHeight);
459
                        requestLayout();
460
                    }
461
                }
462
            };
463
464
    IMediaPlayer.OnPreparedListener mPreparedListener = new IMediaPlayer.OnPreparedListener() {
465
        public void onPrepared(IMediaPlayer mp) {
466
            mPrepareEndTime = System.currentTimeMillis();
467
468
//            monitorRecorder.firstPacket();
469
            mCurrentState = STATE_PREPARED;
470
            mMediaPlayer.pause();
471
472
            // Get the capabilities of the player for this stream
473
            // REMOVED: Metadata
474
475
            if (mOnPreparedListener != null) {
476
                mOnPreparedListener.onPrepared(mMediaPlayer);
477
            }
478
            if (mMediaController != null) {
479
                mMediaController.setEnabled(true);
480
            }
481
            mVideoWidth = mp.getVideoWidth();
482
            mVideoHeight = mp.getVideoHeight();
483
484
//            monitorRecorder.setVideoSize(mVideoHeight, mVideoWidth);
485
//            monitorRecorder.setFirstPlayState(0);
486
//            monitorRecorder.getMetaData(mMediaPlayer._getMetaData());
487
488
            int seekToPosition = mSeekWhenPrepared;  // mSeekWhenPrepared may be changed after seekTo() call
489
            if (seekToPosition != 0) {
490
                seekTo(seekToPosition);
491
            }
492
            if (mVideoWidth != 0 && mVideoHeight != 0) {
493
                Log.i(TAG, "onPrepared mVideoWidth != 0 && mVideoHeight != 0");
494
                //Log.i("@@@@", "video size: " + mVideoWidth +"/"+ mVideoHeight);
495
                // REMOVED: getHolder().setFixedSize(mVideoWidth, mVideoHeight);
496
                if (mRenderView != null) {
497
                    Log.i(TAG, "onPrepared mRenderView != null");
498
                    mRenderView.setVideoSize(mVideoWidth, mVideoHeight);
499
                    mRenderView.setVideoSampleAspectRatio(mVideoSarNum, mVideoSarDen);
500
                    if (!mRenderView.shouldWaitForResize() || mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) {
501
                        Log.i(TAG, "onPrepared 1");
502
                        // We didn't actually change the size (it was already at the size
503
                        // we need), so we won't get a "surface changed" callback, so
504
                        // start the video here instead of in the callback.
505
                        if (mTargetState == STATE_PLAYING) {
506
                            Log.i(TAG, "onPrepared 2");
507
                            start();
508
                            if (mMediaController != null) {
509
                                mMediaController.show();
510
                            }
511
                        } else if (!isPlaying() &&
512
                                (seekToPosition != 0 || getCurrentPosition() > 0)) {
513
                            Log.i(TAG, "onPrepared 3");
514
                            if (mMediaController != null) {
515
                                // Show the media controls when we're paused into a video and make 'em stick.
516
                                mMediaController.show(0);
517
                            }
518
                        }
519
                    }
520
                }
521
            } else {
522
                // We don't know the video size yet, but should start anyway.
523
                // The video size might be reported to us later.
524
                if (mTargetState == STATE_PLAYING) {
525
                    Log.i(TAG, "onPrepared start");
526
                    start();
527
                }
528
            }
529
        }
530
    };
531
532
    private IMediaPlayer.OnCompletionListener mCompletionListener =
533
            new IMediaPlayer.OnCompletionListener() {
534
                public void onCompletion(IMediaPlayer mp) {
535
                    mCurrentState = STATE_PLAYBACK_COMPLETED;
536
                    mTargetState = STATE_PLAYBACK_COMPLETED;
537
                    if (mMediaController != null) {
538
                        mMediaController.hide();
539
                    }
540
                    if (mOnCompletionListener != null) {
541
                        mOnCompletionListener.onCompletion(mMediaPlayer);
542
                    }
543
                }
544
            };
545
546
    private IjkMediaPlayer.OnNativeInvokeListener mNativeInvokeListener = new IjkMediaPlayer.OnNativeInvokeListener() {
547
        @Override
548
        public boolean onNativeInvoke(int what, Bundle args) {
549
            Log.i(TAG, "onNativeInvoke:" + what);
550
            if (mOnNativeInvokeListener != null) {
551
                mOnNativeInvokeListener.onNativeInvoke(what, args);
552
            }
553
            return false;
554
        }
555
    };
556
557
    private IMediaPlayer.OnInfoListener mInfoListener =
558
            new IMediaPlayer.OnInfoListener() {
559
                public boolean onInfo(IMediaPlayer mp, int arg1, int arg2) {
560
                    if (mOnInfoListener != null) {
561
                        mOnInfoListener.onInfo(mp, arg1, arg2);
562
                    }
563
                    switch (arg1) {
564
                        case IMediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING:
565
                            Log.d(TAG, "MEDIA_INFO_VIDEO_TRACK_LAGGING:");
566
                            break;
567
                        case IMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
568
                            Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_START:");
569
                            break;
570
                        case IMediaPlayer.MEDIA_INFO_BUFFERING_START:
571
                            Log.e(TAG, "卡顿时间:" + bufferTime);
572
                            startbufferTime = System.currentTimeMillis();
573
                            if (bufferTime > PURSUETIME && isAutoPursue) {
574
                                bufferTime = 0;
575
                                resume();
576
                                Log.e(TAG, "卡顿重连追帧");
577
                                break;
578
                            }
579
                            if (isAutoPursue) {
580
                                reportError();
581
                            }
582
583
                            Log.d(TAG, "MEDIA_INFO_BUFFERING_START:");
584
                            break;
585
                        case IMediaPlayer.MEDIA_INFO_BUFFERING_END:
586
                            Log.e(TAG, "结束缓冲:" + bufferTime);
587
                            if (startbufferTime != 0 && isAutoPursue) {
588
                                bufferTime = System.currentTimeMillis() - startbufferTime;
589
                                if (bufferTime > 2000) {
590
                                    bufferTime = 0;
591
                                    resume();
592
                                }
593
                            }
594
                            cancelReport();
595
//                            monitorRecorder.BufferEnd();
596
                            Log.d(TAG, "MEDIA_INFO_BUFFERING_END:");
597
                            break;
598
                        case IMediaPlayer.MEDIA_INFO_NETWORK_BANDWIDTH:
599
//                            recorder.setBandwidth(arg2);
600
                            Log.d(TAG, "MEDIA_INFO_NETWORK_BANDWIDTH: " + arg2);
601
                            break;
602
                        case IMediaPlayer.MEDIA_INFO_BAD_INTERLEAVING:
603
                            Log.d(TAG, "MEDIA_INFO_BAD_INTERLEAVING:");
604
                            break;
605
                        case IMediaPlayer.MEDIA_INFO_NOT_SEEKABLE:
606
                            Log.d(TAG, "MEDIA_INFO_NOT_SEEKABLE:");
607
                            break;
608
                        case IMediaPlayer.MEDIA_INFO_METADATA_UPDATE:
609
                            Log.d(TAG, "MEDIA_INFO_METADATA_UPDATE:");
610
                            break;
611
                        case IMediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE:
612
                            Log.d(TAG, "MEDIA_INFO_UNSUPPORTED_SUBTITLE:");
613
                            break;
614
                        case IMediaPlayer.MEDIA_INFO_SUBTITLE_TIMED_OUT:
615
                            Log.d(TAG, "MEDIA_INFO_SUBTITLE_TIMED_OUT:");
616
                            break;
617
                        case IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED:
618
                            mVideoRotationDegree = arg2;
619
                            Log.d(TAG, "MEDIA_INFO_VIDEO_ROTATION_CHANGED: " + arg2);
620
                            if (mRenderView != null)
621
                                mRenderView.setVideoRotation(arg2);
622
                            break;
623
                        case IMediaPlayer.MEDIA_INFO_AUDIO_RENDERING_START:
624
                            Log.d(TAG, "MEDIA_INFO_AUDIO_RENDERING_START:");
625
                            break;
626
                    }
627
                    return true;
628
                }
629
            };
630
631
    private IMediaPlayer.OnErrorListener mErrorListener =
632
            new IMediaPlayer.OnErrorListener() {
633
                public boolean onError(IMediaPlayer mp, int framework_err, int impl_err) {
634
                    Log.e(TAG, "Error: " + framework_err + "," + impl_err);
635
636
//                    monitorRecorder.errorDate("Error: " + framework_err + "," + impl_err);
637
638
                    mCurrentState = STATE_ERROR;
639
                    mTargetState = STATE_ERROR;
640
                    if (mMediaController != null) {
641
                        mMediaController.hide();
642
                    }
643
644
                    /* If an error handler has been supplied, use it and finish. */
645
                    if (mOnErrorListener != null) {
646
                        if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) {
647
                            return true;
648
                        }
649
                    }
650
651
                    /* Otherwise, pop up an error dialog so the user knows that
652
                     * something bad has happened. Only try and pop up the dialog
653
                     * if we're attached to a window. When we're going away and no
654
                     * longer have a window, don't bother showing the user an error.
655
                     */
656
                    if (getWindowToken() != null) {
657
                        String messageId;
658
659
                        if (framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
660
                            messageId = "Invalid progressive playback";
661
                        } else {
662
                            messageId = "Unknown";
663
                        }
664
665
                        new AlertDialog.Builder(getContext())
666
                                .setMessage(messageId)
667
                                .setPositiveButton("OK",
668
                                        new DialogInterface.OnClickListener() {
669
                                            public void onClick(DialogInterface dialog, int whichButton) {
670
                                                /* If we get here, there is no onError listener, so
671
                                                 * at least inform them that the video is over.
672
                                                 */
673
                                                if (mOnCompletionListener != null) {
674
                                                    mOnCompletionListener.onCompletion(mMediaPlayer);
675
                                                }
676
                                            }
677
                                        })
678
                                .setCancelable(false)
679
                                .show();
680
                    }
681
                    return true;
682
                }
683
            };
684
685
    private IMediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
686
            new IMediaPlayer.OnBufferingUpdateListener() {
687
                public void onBufferingUpdate(IMediaPlayer mp, int percent) {
688
                    mCurrentBufferPercentage = percent;
689
                }
690
            };
691
692
    private IMediaPlayer.OnSeekCompleteListener mSeekCompleteListener = new IMediaPlayer.OnSeekCompleteListener() {
693
694
        @Override
695
        public void onSeekComplete(IMediaPlayer mp) {
696
            mSeekEndTime = System.currentTimeMillis();
697
        }
698
    };
699
700
    /**
701
     * Register a callback to be invoked when the media file
702
     * is loaded and ready to go.
703
     *
704
     * @param l The callback that will be run
705
     */
706
    public void setOnPreparedListener(IMediaPlayer.OnPreparedListener l) {
707
        mOnPreparedListener = l;
708
    }
709
710
    /**
711
     * Register a callback to be invoked when the end of a media file
712
     * has been reached during playback.
713
     *
714
     * @param l The callback that will be run
715
     */
716
    public void setOnCompletionListener(IMediaPlayer.OnCompletionListener l) {
717
        mOnCompletionListener = l;
718
    }
719
720
    /**
721
     * Register a callback to be invoked when an error occurs
722
     * during playback or setup.  If no listener is specified,
723
     * or if the listener returned false, VideoView will inform
724
     * the user of any errors.
725
     *
726
     * @param l The callback that will be run
727
     */
728
    public void setOnErrorListener(IMediaPlayer.OnErrorListener l) {
729
        mOnErrorListener = l;
730
    }
731
732
    /**
733
     * Register a callback to be invoked when an informational event
734
     * occurs during playback or setup.
735
     *
736
     * @param l The callback that will be run
737
     */
738
    public void setOnInfoListener(IMediaPlayer.OnInfoListener l) {
739
        mOnInfoListener = l;
740
    }
741
742
743
    public void setOnVideoSizeListener(IMediaPlayer.OnVideoSizeChangedListener l) {
744
        mOnVideoSizeChangedListener = l;
745
    }
746
747
    /**
748
     * @see AVAPP_EVENT_WILL_HTTP_OPEN
749
     * @see AVAPP_EVENT_HTTP_CODE
750
     * @param l
751
     */
752
    public void setOnNativeInvokeListener(IjkMediaPlayer.OnNativeInvokeListener l) {
753
        mOnNativeInvokeListener = l;
754
    }
755
756
    // REMOVED: mSHCallback
757
    private void bindSurfaceHolder(IMediaPlayer mp, IRenderView.ISurfaceHolder holder) {
758
        if (mp == null)
759
            return;
760
761
        if (holder == null) {
762
            mp.setSurface(null);
763
            return;
764
        }
765
766
        holder.bindToMediaPlayer(mp);
767
    }
768
769
    IRenderView.IRenderCallback mSHCallback = new IRenderView.IRenderCallback() {
770
        @Override
771
        public void onSurfaceChanged(@NonNull IRenderView.ISurfaceHolder holder, int format, int w, int h) {
772
            if (holder.getRenderView() != mRenderView) {
773
                Log.e(TAG, "onSurfaceChanged: unmatched render callback\n");
774
                return;
775
            }
776
            Log.i(TAG, "onSurfaceChanged");
777
            mSurfaceWidth = w;
778
            mSurfaceHeight = h;
779
            boolean isValidState = (mTargetState == STATE_PLAYING);
780
            boolean hasValidSize = !mRenderView.shouldWaitForResize() || (mVideoWidth == w && mVideoHeight == h);
781
            if (mMediaPlayer != null && isValidState && hasValidSize) {
782
                if (mSeekWhenPrepared != 0) {
783
                    seekTo(mSeekWhenPrepared);
784
                }
785
                start();
786
            }
787
        }
788
789
        @Override
790
        public void onSurfaceCreated(@NonNull IRenderView.ISurfaceHolder holder, int width, int height) {
791
            if (holder.getRenderView() != mRenderView) {
792
                Log.e(TAG, "onSurfaceCreated: unmatched render callback\n");
793
                return;
794
            }
795
            Log.i(TAG, "onSurfaceCreated");
796
            mSurfaceHolder = holder;
797
            if (mMediaPlayer != null) {
798
                Log.i(TAG, "onSurfaceCreated bindSurfaceHolder");
799
                bindSurfaceHolder(mMediaPlayer, holder);
800
            } else {
801
                Log.i(TAG, "onSurfaceCreated openVideo");
802
                // onSurfaceCreated在调用过start之后触发
803
                if (mTargetState == STATE_PLAYING) {
804
                    openVideo();
805
                    if (mMediaPlayer != null) {
806
                        Log.i(TAG, "onSurfaceCreated bindSurfaceHolder");
807
                        bindSurfaceHolder(mMediaPlayer, holder);
808
                        mCurrentState = STATE_PLAYING;
809
                        start();
810
                    }
811
                }
812
            }
813
        }
814
815
        @Override
816
        public void onSurfaceDestroyed(@NonNull IRenderView.ISurfaceHolder holder) {
817
            Log.i(TAG, "onSurfaceDestroyed1");
818
            if (holder.getRenderView() != mRenderView) {
819
                Log.e(TAG, "onSurfaceDestroyed: unmatched render callback\n");
820
                return;
821
            }
822
            Log.i(TAG, "onSurfaceDestroyed2");
823
            // after we return from this we can't use the surface any more
824
            mSurfaceHolder = null;
825
            // REMOVED: if (mMediaController != null) mMediaController.hide();
826
            // REMOVED: release(true);
827
//            releaseWithoutStop();
828
            if (mMediaController != null) mMediaController.hide();
829
//            release(true);
830
            releaseWithoutStop();
831
        }
832
    };
833
834
    public void releaseWithoutStop() {
835
        if (mMediaPlayer != null){
836
            Log.i(TAG, "releaseWithoutStop");
837
            mMediaPlayer.setSurface(null);
838
        }
839
    }
840
841
    /*
842
     * release the media player in any state
843
     */
844
    public void release(boolean cleartargetstate) {
845
846
        if (mMediaPlayer != null) {
847
            Log.i(TAG, "release:" + cleartargetstate);
848
            mMediaPlayer.reset();
849
            mMediaPlayer.release();
850
//            mHandler.removeMessages(MSG_CACHE_DRU);
851
//            monitorRecorder.endRecode();
852
            mMediaPlayer = null;
853
            // REMOVED: mPendingSubtitleTracks.clear();
854
            mCurrentState = STATE_IDLE;
855
            if (cleartargetstate) {
856
                mTargetState = STATE_IDLE;
857
            }
858
            AudioManager am = (AudioManager) mAppContext.getSystemService(Context.AUDIO_SERVICE);
859
            am.abandonAudioFocus(null);
860
        }
861
    }
862
863
    @Override
864
    public boolean onTouchEvent(MotionEvent ev) {
865
        if (isInPlaybackState() && mMediaController != null) {
866
            toggleMediaControlsVisiblity();
867
        }
868
        return false;
869
    }
870
871
    @Override
872
    public boolean onTrackballEvent(MotionEvent ev) {
873
        if (isInPlaybackState() && mMediaController != null) {
874
            toggleMediaControlsVisiblity();
875
        }
876
        return false;
877
    }
878
879
    @Override
880
    public boolean onKeyDown(int keyCode, KeyEvent event) {
881
        boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
882
                keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
883
                keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
884
                keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
885
                keyCode != KeyEvent.KEYCODE_MENU &&
886
                keyCode != KeyEvent.KEYCODE_CALL &&
887
                keyCode != KeyEvent.KEYCODE_ENDCALL;
888
        if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
889
            if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
890
                    keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
891
                if (mMediaPlayer.isPlaying()) {
892
                    pause();
893
                    mMediaController.show();
894
                } else {
895
                    start();
896
                    mMediaController.hide();
897
                }
898
                return true;
899
            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
900
                if (!mMediaPlayer.isPlaying()) {
901
                    start();
902
                    mMediaController.hide();
903
                }
904
                return true;
905
            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
906
                    || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
907
                if (mMediaPlayer.isPlaying()) {
908
                    pause();
909
                    mMediaController.show();
910
                }
911
                return true;
912
            } else {
913
                toggleMediaControlsVisiblity();
914
            }
915
        }
916
917
        return super.onKeyDown(keyCode, event);
918
    }
919
920
    private void toggleMediaControlsVisiblity() {
921
        if (mMediaController.isShowing()) {
922
            mMediaController.hide();
923
        } else {
924
            mMediaController.show();
925
        }
926
    }
927
928
    @Override
929
    public void start() {
930
        Log.i(TAG, "start");
931
        if (isInPlaybackState()) {
932
            Log.i(TAG, "start isInPlaybackState");
933
            mMediaPlayer.start();
934
            mCurrentState = STATE_PLAYING;
935
            mRenderView.getView().setBackgroundDrawable(null);
936
        } else {
937
            Log.i(TAG, "start isInPlaybackState false mMediaPlayer == null:" + (mMediaPlayer == null) + " mCurrentState" + mCurrentState);
938
        }
939
        mTargetState = STATE_PLAYING;
940
    }
941
942
    @Override
943
    public void pause() {
944
        if (isInPlaybackState()) {
945
            if (mMediaPlayer.isPlaying()) {
946
                mMediaPlayer.pause();
947
                mCurrentState = STATE_PAUSED;
948
            }
949
        }
950
        mTargetState = STATE_PAUSED;
951
    }
952
953
    public void suspend() {
954
        release(false);
955
    }
956
957
    public void resume() {
958
        openVideo();
959
    }
960
961
    @Override
962
    public int getDuration() {
963
        if (isInPlaybackState()) {
964
            return (int) mMediaPlayer.getDuration();
965
        }
966
967
        return -1;
968
    }
969
970
    @Override
971
    public int getCurrentPosition() {
972
        if (isInPlaybackState()) {
973
            if (mCurrentState == STATE_PLAYBACK_COMPLETED) {
974
                return (int) mMediaPlayer.getDuration();
975
            }
976
            return (int) mMediaPlayer.getCurrentPosition();
977
        }
978
        return 0;
979
    }
980
981
    @Override
982
    public void seekTo(int msec) {
983
        if (isInPlaybackState()) {
984
            mSeekStartTime = System.currentTimeMillis();
985
            mMediaPlayer.seekTo(msec);
986
            mSeekWhenPrepared = 0;
987
        } else {
988
            mSeekWhenPrepared = msec;
989
        }
990
    }
991
992
    @Override
993
    public boolean isPlaying() {
994
        return isInPlaybackState() && mMediaPlayer.isPlaying();
995
    }
996
997
    @Override
998
    public int getBufferPercentage() {
999
        if (mMediaPlayer != null) {
1000
            return mCurrentBufferPercentage;
1001
        }
1002
        return 0;
1003
    }
1004
1005
    private boolean isInPlaybackState() {
1006
        return (mMediaPlayer != null &&
1007
                mCurrentState != STATE_ERROR &&
1008
                mCurrentState != STATE_IDLE &&
1009
                mCurrentState != STATE_PREPARING);
1010
    }
1011
1012
    @Override
1013
    public boolean canPause() {
1014
        return mCanPause;
1015
    }
1016
1017
    @Override
1018
    public boolean canSeekBackward() {
1019
        return mCanSeekBack;
1020
    }
1021
1022
    @Override
1023
    public boolean canSeekForward() {
1024
        return mCanSeekForward;
1025
    }
1026
1027
    @Override
1028
    public int getAudioSessionId() {
1029
        return mMediaPlayer.getAudioSessionId();
1030
    }
1031
1032
    // REMOVED: getAudioSessionId();
1033
    // REMOVED: onAttachedToWindow();
1034
    // REMOVED: onDetachedFromWindow();
1035
    // REMOVED: onLayout();
1036
    // REMOVED: draw();
1037
    // REMOVED: measureAndLayoutSubtitleWidget();
1038
    // REMOVED: setSubtitleWidget();
1039
    // REMOVED: getSubtitleLooper();
1040
    //-------------------------
1041
    // Extend: Aspect Ratio
1042
    //-------------------------
1043
1044
    private static final int[] s_allAspectRatio = {
1045
            IRenderView.AR_ASPECT_FIT_PARENT,
1046
            IRenderView.AR_ASPECT_FILL_PARENT,
1047
            IRenderView.AR_ASPECT_WRAP_CONTENT,
1048
            IRenderView.AR_MATCH_PARENT,
1049
            IRenderView.AR_16_9_FIT_PARENT,
1050
            IRenderView.AR_4_3_FIT_PARENT};
1051
    private int mCurrentAspectRatioIndex = 0;
1052
    private int mCurrentAspectRatio = s_allAspectRatio[0];
1053
1054
    public int toggleAspectRatio() {
1055
        mCurrentAspectRatioIndex++;
1056
        mCurrentAspectRatioIndex %= s_allAspectRatio.length;
1057
1058
        mCurrentAspectRatio = s_allAspectRatio[mCurrentAspectRatioIndex];
1059
        if (mRenderView != null)
1060
            mRenderView.setAspectRatio(mCurrentAspectRatio);
1061
        return mCurrentAspectRatio;
1062
    }
1063
1064
    public void setAspectRatio(int aspectRatio) {
1065
        mCurrentAspectRatio = aspectRatio;
1066
        if (mRenderView != null)
1067
            mRenderView.setAspectRatio(mCurrentAspectRatio);
1068
    }
1069
1070
    public ITrackInfo[] getTrackInfo() {
1071
        if (mMediaPlayer == null)
1072
            return null;
1073
1074
        return mMediaPlayer.getTrackInfo();
1075
    }
1076
1077
    public void selectTrack(int stream) {
1078
        MediaPlayerCompat.selectTrack(mMediaPlayer, stream);
1079
    }
1080
1081
    public void deselectTrack(int stream) {
1082
        MediaPlayerCompat.deselectTrack(mMediaPlayer, stream);
1083
    }
1084
1085
    public int getSelectedTrack(int trackType) {
1086
        return MediaPlayerCompat.getSelectedTrack(mMediaPlayer, trackType);
1087
    }
1088
1089
    public void fullScreen(Activity activity) {
1090
        if (!isFullState) {
1091
            if (activity.getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
1092
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
1093
            }
1094
            activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
1095
                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
1096
//            DisplayMetrics metrics = new DisplayMetrics();
1097
//            activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
1098
//            mRawParams = getLayoutParams();
1099
//            ViewGroup.LayoutParams fullParams;
1100
//            if (mRawParams instanceof RelativeLayout.LayoutParams) {
1101
//                fullParams = new RelativeLayout.LayoutParams(metrics.widthPixels, metrics.heightPixels);
1102
//            } else if (mRawParams instanceof LinearLayout.LayoutParams) {
1103
//                fullParams = new LinearLayout.LayoutParams(metrics.widthPixels, metrics.heightPixels);
1104
//            } else if (mRawParams instanceof LayoutParams) {
1105
//                fullParams = new LayoutParams(metrics.widthPixels, metrics.heightPixels);
1106
//            } else {
1107
//                new AlertDialog.Builder(getContext())
1108
//                        .setMessage("nonsupport parent layout, please do it by yourself")
1109
//                        .setPositiveButton("OK",
1110
//                                new DialogInterface.OnClickListener() {
1111
//                                    public void onClick(DialogInterface dialog, int whichButton) {
1112
//                                    }
1113
//                                })
1114
//                        .setCancelable(false)
1115
//                        .show();
1116
//                return;
1117
//            }
1118
//            setLayoutParams(fullParams);
1119
            isFullState = true;
1120
        }
1121
    }
1122
1123
    public void exitFullScreen(Activity activity) {
1124
1125
        if (isFullState) {
1126
            if (activity.getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
1127
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
1128
            }
1129
//            setLayoutParams(mRawParams);
1130
            isFullState = false;
1131
        }
1132
    }
1133
1134
1135
    // TODO: 16/5/20 设置播放前至少缓存时间
1136
    private void setCacheDuration(long cacheDuration) {
1137
        this.cacheDuration = cacheDuration;
1138
    }
1139
1140
    public long cacheDuration;
1141
1142
    /**
1143
     * 设置默认背景图片
1144
     *
1145
     * @param rec
1146
     */
1147
    public void setImage(int rec) {
1148
        if (mRenderView != null) {
1149
            mRenderView.getView().setBackgroundResource(rec);
1150
        }
1151
    }
1152
1153
    public void setImage(Drawable background) {
1154
        if (mRenderView != null) {
1155
            mRenderView.getView().setBackgroundDrawable(background);
1156
        }
1157
    }
1158
1159
    /**
1160
     * 设置缓冲区大小 单位(B) 默认 15MB
1161
     *
1162
     * @param size
1163
     */
1164
    public void setBufferSize(int size) {
1165
        bufferSize = size;
1166
    }
1167
1168
    /**
1169
     * 设置是否自动开始播放 默认false
1170
     *
1171
     * @param autoPlay
1172
     */
1173
    public void setAutoStart(boolean autoPlay) {
1174
        isAutoPlay = autoPlay;
1175
    }
1176
1177
1178
    /**
1179
     * 设置播放速度
1180
     */
1181
    public void setSpeed(float speed) {
1182
        playSpeed = speed;
1183
        if (mMediaPlayer != null) {
1184
            mMediaPlayer.setSpeed(speed);
1185
        }
1186
    }
1187
1188
    public float getSpeed(float speed) {
1189
        if (mMediaPlayer != null) {
1190
            return mMediaPlayer.getSpeed(.0f);
1191
        }
1192
        return .0f;
1193
    }
1194
1195
1196
1197
    private void reportError() {
1198
        Log.e(TAG, "reportError");
1199
        postDelayed(reconnection, 20000);
1200
    }
1201
1202
    private void cancelReport() {
1203
        Log.e(TAG, "cancelReport");
1204
        removeCallbacks(reconnection);
1205
    }
1206
1207
    private Runnable reconnection = new Runnable() {
1208
        @Override
1209
        public void run() {
1210
            release(true);
1211
            mErrorListener.onError(mMediaPlayer, -1001, 0);
1212
        }
1213
    };
1214
}
1215

二进制
app/src/main/res/drawable-xxhdpi/icon_at.png


二进制
app/src/main/res/drawable-xxhdpi/icon_back.png


二进制
app/src/main/res/drawable-xxhdpi/icon_close.png


二进制
app/src/main/res/drawable-xxhdpi/icon_comment.png


二进制
app/src/main/res/drawable-xxhdpi/icon_expend.png


二进制
app/src/main/res/drawable-xxhdpi/icon_forward.png


二进制
app/src/main/res/drawable-xxhdpi/icon_likeed.png


二进制
app/src/main/res/drawable-xxhdpi/icon_more.png


二进制
app/src/main/res/drawable-xxhdpi/icon_write_comment.png


+ 5 - 5
app/src/main/res/layout/activity_videodetails.xml

@ -21,7 +21,6 @@
21 21
            android:layout_width="wrap_content"
22 22
            android:layout_height="wrap_content"
23 23
            android:layout_centerInParent="true"
24
            android:text="待问答问题"
25 24
            android:textColor="#ffffff"
26 25
            android:textSize="18sp" />
27 26
@ -30,18 +29,19 @@
30 29
            android:id="@+id/vd_title_back"
31 30
            android:layout_width="wrap_content"
32 31
            android:layout_height="match_parent"
33
            android:layout_alignParentLeft="true"
32
            android:layout_alignParentStart="true"
34 33
            android:paddingLeft="15dp"
35
            android:paddingRight="15dp"  />
34
            android:paddingRight="15dp"
35
            android:src="@drawable/icon_back" />
36 36
37 37
        <ImageView
38 38
            android:id="@+id/vd_title_dot"
39 39
            android:layout_width="wrap_content"
40 40
            android:layout_height="match_parent"
41
42 41
            android:layout_alignParentRight="true"
43 42
            android:paddingLeft="15dp"
44
            android:paddingRight="15dp" />
43
            android:paddingRight="15dp"
44
            android:src="@drawable/icon_more" />
45 45
46 46
    </RelativeLayout>
47 47
</RelativeLayout>

+ 2 - 2
app/src/main/res/layout/sv_video_publish_info.xml

@ -12,7 +12,7 @@
12 12
        android:layout_alignParentEnd="true"
13 13
        android:layout_marginTop="14dp"
14 14
        android:layout_marginEnd="14dp"
15
        android:background="@drawable/icon_dialog_close" />
15
        android:background="@drawable/icon_close" />
16 16
17 17
18 18
    <LinearLayout
@ -32,7 +32,7 @@
32 32
            android:layout_height="12dp"
33 33
            android:layout_marginStart="12dp"
34 34
            android:layout_marginEnd="4dp"
35
            android:background="#fff" />
35
            android:background="@drawable/icon_at" />
36 36
37 37
        <TextView
38 38
            android:id="@+id/video_publish_topic_con"

+ 32 - 35
app/src/main/res/layout/view_show_bottom.xml

@ -5,22 +5,22 @@
5 5
        android:id="@+id/sv_show_bottom"
6 6
        android:layout_width="match_parent"
7 7
        android:layout_height="50dp"
8
        android:layout_alignParentBottom="true">
8
        android:layout_alignParentBottom="true"
9
        android:background="#000">
9 10
10 11
        <LinearLayout
11 12
            android:id="@+id/sv_show_forward"
12 13
            android:layout_width="wrap_content"
13 14
            android:layout_height="30dp"
14
            android:layout_alignParentRight="true"
15
            android:layout_alignParentEnd="true"
15 16
            android:layout_centerVertical="true"
16
            android:layout_marginRight="15dp"
17
            android:layout_marginEnd="15dp"
17 18
            android:gravity="center_vertical">
18 19
19 20
            <ImageView
20
                android:layout_width="30dp"
21
                android:layout_height="30dp"
22
                android:layout_centerVertical="true"
23
                android:background="#fff" />
21
                android:layout_width="19dp"
22
                android:layout_height="19dp"
23
                android:background="@drawable/icon_forward" />
24 24
25 25
            <TextView
26 26
                android:layout_width="wrap_content"
@ -35,20 +35,20 @@
35 35
            android:layout_width="wrap_content"
36 36
            android:layout_height="30dp"
37 37
            android:layout_centerVertical="true"
38
            android:layout_marginRight="15dp"
38
            android:layout_marginEnd="15dp"
39 39
            android:layout_toStartOf="@+id/sv_show_forward"
40 40
            android:gravity="center_vertical">
41 41
42 42
            <ImageView
43
                android:layout_width="30dp"
44
                android:layout_height="30dp"
45
                android:layout_centerVertical="true"
46
                android:background="#fff" />
43
                android:layout_width="19dp"
44
                android:layout_height="19dp"
45
                android:background="@drawable/icon_comment" />
47 46
48 47
            <TextView
49 48
                android:id="@+id/sv_show_comment_count_tv"
50 49
                android:layout_width="wrap_content"
51 50
                android:layout_height="wrap_content"
51
                android:textColor="#888888"
52 52
                android:textSize="12sp" />
53 53
54 54
        </LinearLayout>
@ -64,15 +64,15 @@
64 64
65 65
            <ImageView
66 66
                android:id="@+id/sv_show_like_img"
67
                android:layout_width="30dp"
68
                android:layout_height="30dp"
69
                android:layout_centerVertical="true"
70
                android:background="#fff" />
67
                android:layout_width="19dp"
68
                android:layout_height="19dp"
69
                android:background="@drawable/icon_likeed" />
71 70
72 71
            <TextView
73 72
                android:id="@+id/sv_show_like_tv"
74 73
                android:layout_width="wrap_content"
75 74
                android:layout_height="wrap_content"
75
                android:textColor="#888888"
76 76
                android:textSize="12sp" />
77 77
78 78
        </LinearLayout>
@ -82,16 +82,15 @@
82 82
            android:layout_width="match_parent"
83 83
            android:layout_height="match_parent"
84 84
            android:layout_centerVertical="true"
85
            android:layout_marginRight="15dp"
85
            android:layout_marginEnd="15dp"
86 86
            android:layout_toStartOf="@+id/sv_show_like_ll"
87 87
            android:gravity="center_vertical">
88 88
89 89
            <ImageView
90
                android:layout_width="30dp"
91
                android:layout_height="30dp"
92
                android:layout_centerVertical="true"
93
                android:layout_marginLeft="15dp"
94
                android:background="#fff" />
90
                android:layout_width="19dp"
91
                android:layout_height="19dp"
92
                android:layout_marginStart="15dp"
93
                android:background="@drawable/icon_write_comment" />
95 94
96 95
            <TextView
97 96
                android:layout_width="wrap_content"
@ -119,24 +118,24 @@
119 118
        android:layout_marginBottom="23dp"
120 119
        android:ellipsize="end"
121 120
        android:maxLines="3"
122
         android:textSize="14sp" />
121
        android:textSize="14sp" />
123 122
124
    <View
123
    <ImageView
125 124
        android:id="@+id/sv_show_tvcon_more"
126 125
        android:layout_width="30dp"
127 126
        android:layout_height="30dp"
128 127
        android:layout_above="@+id/sv_show_bottom"
129 128
        android:layout_alignParentEnd="true"
129
        android:padding="8dp"
130 130
        android:layout_marginBottom="28dp"
131
        android:rotation="90"
132
        android:background="@drawable/ssdk_country_back_arrow" />
131
        android:src="@drawable/icon_expend" />
133 132
134 133
    <RelativeLayout
135 134
        android:id="@+id/sv_show_user_info"
136 135
        android:layout_width="wrap_content"
137 136
        android:layout_height="34dp"
138 137
        android:layout_above="@+id/sv_show_tvcon"
139
        android:layout_marginLeft="15dp"
138
        android:layout_marginStart="15dp"
140 139
        android:layout_marginBottom="5dp">
141 140
142 141
        <ImageView
@ -149,9 +148,8 @@
149 148
            android:id="@+id/sv_show_user_name"
150 149
            android:layout_width="wrap_content"
151 150
            android:layout_height="wrap_content"
152
            android:layout_marginLeft="5dp"
151
            android:layout_marginStart="5dp"
153 152
            android:layout_toEndOf="@+id/sv_show_user_avatar"
154
            android:text="adsdasasdad"
155 153
            android:textColor="#fff"
156 154
            android:textSize="12sp" />
157 155
@ -160,8 +158,7 @@
160 158
            android:layout_width="wrap_content"
161 159
            android:layout_height="wrap_content"
162 160
            android:layout_below="@+id/sv_show_user_name"
163
            android:layout_alignLeft="@+id/sv_show_user_name"
164
            android:text="adsdasasdad"
161
            android:layout_alignStart="@+id/sv_show_user_name"
165 162
            android:textColor="#fff"
166 163
            android:textSize="12sp" />
167 164
    </RelativeLayout>
@ -177,21 +174,21 @@
177 174
        android:background="#b3303030"
178 175
        android:gravity="center_vertical">
179 176
180
        <View
177
        <ImageView
181 178
            android:layout_width="12dp"
182 179
            android:layout_height="12dp"
183 180
            android:layout_marginStart="12dp"
184 181
            android:layout_marginEnd="4dp"
185
            android:background="#fff" />
182
            android:src="@drawable/icon_at" />
186 183
187 184
        <TextView
188 185
            android:id="@+id/sv_show_topic_con"
189 186
            android:layout_width="wrap_content"
190 187
            android:layout_height="wrap_content"
191
            android:layout_marginRight="12dp"
188
            android:layout_marginEnd="12dp"
192 189
            android:ellipsize="end"
193 190
            android:maxLines="1"
194
             android:textColor="#fff"
191
            android:textColor="#fff"
195 192
            android:textSize="11sp" />
196 193
    </LinearLayout>
197 194

+ 5 - 6
app/src/main/res/layout/view_show_comment.xml

@ -15,14 +15,13 @@
15 15
        android:textSize="14sp" />
16 16
17 17
18
    <View
18
    <ImageView
19 19
        android:id="@+id/show_comment_close"
20
        android:layout_width="22dp"
21
        android:layout_height="22dp"
20
        android:layout_width="40dp"
21
        android:layout_height="40dp"
22 22
        android:layout_alignParentEnd="true"
23
        android:layout_marginTop="9dp"
24
        android:layout_marginEnd="14dp"
25
        android:background="@drawable/icon_dialog_close"  />
23
        android:padding="6dp"
24
        android:src="@drawable/icon_close"  />
26 25
27 26
    <View
28 27
        android:layout_width="match_parent"

+ 1 - 0
ijkplayer-java/.gitignore

@ -0,0 +1 @@
1
/build

+ 21 - 0
ijkplayer-java/build.gradle

@ -0,0 +1,21 @@
1
apply plugin: 'com.android.library'
2
3
android {
4
5
      compileSdkVersion 26
6
    buildToolsVersion '28.0.3'
7
    defaultConfig {
8
        minSdkVersion 14
9
        targetSdkVersion 26
10
    }
11
    buildTypes {
12
        release {
13
            minifyEnabled false
14
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
15
        }
16
    }
17
}
18
19
dependencies {
20
//    implementation fileTree(dir: 'libs', include: ['*.jar'])
21
}

+ 3 - 0
ijkplayer-java/gradle.properties

@ -0,0 +1,3 @@
1
POM_NAME=ijkplayer-java
2
POM_ARTIFACT_ID=ijkplayer-java
3
POM_PACKAGING=aar

+ 17 - 0
ijkplayer-java/proguard-rules.pro

@ -0,0 +1,17 @@
1
# Add project specific ProGuard rules here.
2
# By default, the flags in this file are appended to flags specified
3
# in /opt/android/ADK/tools/proguard/proguard-android.txt
4
# You can edit the include path and order by changing the proguardFiles
5
# directive in build.gradle.
6
#
7
# For more details, see
8
#   http://developer.android.com/guide/developing/tools/proguard.html
9
10
# Add any project specific keep options here:
11
12
# If your project uses WebView with JS, uncomment the following
13
# and specify the fully qualified class name to the JavaScript interface
14
# class:
15
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16
#   public *;
17
#}

+ 13 - 0
ijkplayer-java/src/androidTest/java/tv/danmaku/ijk/media/player/ApplicationTest.java

@ -0,0 +1,13 @@
1
package tv.danmaku.ijk.media.player;
2
3
import android.app.Application;
4
import android.test.ApplicationTestCase;
5
6
/**
7
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
8
 */
9
public class ApplicationTest extends ApplicationTestCase<Application> {
10
    public ApplicationTest() {
11
        super(Application.class);
12
    }
13
}

+ 4 - 0
ijkplayer-java/src/main/AndroidManifest.xml

@ -0,0 +1,4 @@
1
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
    package="tv.danmaku.ijk.media.player" >
3
4
</manifest>

+ 109 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/AbstractMediaPlayer.java

@ -0,0 +1,109 @@
1
/*
2
 * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
20
21
@SuppressWarnings("WeakerAccess")
22
public abstract class AbstractMediaPlayer implements IMediaPlayer {
23
    private OnPreparedListener mOnPreparedListener;
24
    private OnCompletionListener mOnCompletionListener;
25
    private OnBufferingUpdateListener mOnBufferingUpdateListener;
26
    private OnSeekCompleteListener mOnSeekCompleteListener;
27
    private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
28
    private OnErrorListener mOnErrorListener;
29
    private OnInfoListener mOnInfoListener;
30
31
    public final void setOnPreparedListener(OnPreparedListener listener) {
32
        mOnPreparedListener = listener;
33
    }
34
35
    public final void setOnCompletionListener(OnCompletionListener listener) {
36
        mOnCompletionListener = listener;
37
    }
38
39
    public final void setOnBufferingUpdateListener(
40
            OnBufferingUpdateListener listener) {
41
        mOnBufferingUpdateListener = listener;
42
    }
43
44
    public final void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
45
        mOnSeekCompleteListener = listener;
46
    }
47
48
    public final void setOnVideoSizeChangedListener(
49
            OnVideoSizeChangedListener listener) {
50
        mOnVideoSizeChangedListener = listener;
51
    }
52
53
    public final void setOnErrorListener(OnErrorListener listener) {
54
        mOnErrorListener = listener;
55
    }
56
57
    public final void setOnInfoListener(OnInfoListener listener) {
58
        mOnInfoListener = listener;
59
    }
60
61
    public void resetListeners() {
62
        mOnPreparedListener = null;
63
        mOnBufferingUpdateListener = null;
64
        mOnCompletionListener = null;
65
        mOnSeekCompleteListener = null;
66
        mOnVideoSizeChangedListener = null;
67
        mOnErrorListener = null;
68
        mOnInfoListener = null;
69
    }
70
71
    protected final void notifyOnPrepared() {
72
        if (mOnPreparedListener != null)
73
            mOnPreparedListener.onPrepared(this);
74
    }
75
76
    protected final void notifyOnCompletion() {
77
        if (mOnCompletionListener != null)
78
            mOnCompletionListener.onCompletion(this);
79
    }
80
81
    protected final void notifyOnBufferingUpdate(int percent) {
82
        if (mOnBufferingUpdateListener != null)
83
            mOnBufferingUpdateListener.onBufferingUpdate(this, percent);
84
    }
85
86
    protected final void notifyOnSeekComplete() {
87
        if (mOnSeekCompleteListener != null)
88
            mOnSeekCompleteListener.onSeekComplete(this);
89
    }
90
91
    protected final void notifyOnVideoSizeChanged(int width, int height,
92
                                                  int sarNum, int sarDen) {
93
        if (mOnVideoSizeChangedListener != null)
94
            mOnVideoSizeChangedListener.onVideoSizeChanged(this, width, height,
95
                    sarNum, sarDen);
96
    }
97
98
    protected final boolean notifyOnError(int what, int extra) {
99
        return mOnErrorListener != null && mOnErrorListener.onError(this, what, extra);
100
    }
101
102
    protected final boolean notifyOnInfo(int what, int extra) {
103
        return mOnInfoListener != null && mOnInfoListener.onInfo(this, what, extra);
104
    }
105
106
    public void setDataSource(IMediaDataSource mediaDataSource) {
107
        throw new UnsupportedOperationException();
108
    }
109
}

+ 418 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/AndroidMediaPlayer.java

@ -0,0 +1,418 @@
1
/*
2
 * Copyright (C) 2006 The Android Open Source Project
3
 * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.com>
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
package tv.danmaku.ijk.media.player;
19
20
import android.annotation.TargetApi;
21
import android.content.Context;
22
import android.media.AudioManager;
23
import android.media.MediaDataSource;
24
import android.media.MediaPlayer;
25
import android.net.Uri;
26
import android.os.Build;
27
import android.text.TextUtils;
28
import android.view.Surface;
29
import android.view.SurfaceHolder;
30
31
import java.io.FileDescriptor;
32
import java.io.IOException;
33
import java.lang.ref.WeakReference;
34
import java.util.Map;
35
36
import tv.danmaku.ijk.media.player.misc.AndroidTrackInfo;
37
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
38
import tv.danmaku.ijk.media.player.misc.ITrackInfo;
39
import tv.danmaku.ijk.media.player.pragma.DebugLog;
40
41
public class AndroidMediaPlayer extends AbstractMediaPlayer {
42
    private final MediaPlayer mInternalMediaPlayer;
43
    private final AndroidMediaPlayerListenerHolder mInternalListenerAdapter;
44
    private String mDataSource;
45
    private MediaDataSource mMediaDataSource;
46
47
    private final Object mInitLock = new Object();
48
    private boolean mIsReleased;
49
50
    private static MediaInfo sMediaInfo;
51
52
    public AndroidMediaPlayer() {
53
        synchronized (mInitLock) {
54
            mInternalMediaPlayer = new MediaPlayer();
55
        }
56
        mInternalMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
57
        mInternalListenerAdapter = new AndroidMediaPlayerListenerHolder(this);
58
        attachInternalListeners();
59
    }
60
61
    public MediaPlayer getInternalMediaPlayer() {
62
        return mInternalMediaPlayer;
63
    }
64
65
    @Override
66
    public void setDisplay(SurfaceHolder sh) {
67
        synchronized (mInitLock) {
68
            if (!mIsReleased) {
69
                mInternalMediaPlayer.setDisplay(sh);
70
            }
71
        }
72
    }
73
74
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
75
    @Override
76
    public void setSurface(Surface surface) {
77
        mInternalMediaPlayer.setSurface(surface);
78
    }
79
80
    @Override
81
    public void setDataSource(Context context, Uri uri)
82
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
83
        mInternalMediaPlayer.setDataSource(context, uri);
84
    }
85
86
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
87
    @Override
88
    public void setDataSource(Context context, Uri uri, Map<String, String> headers)
89
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
90
        mInternalMediaPlayer.setDataSource(context, uri, headers);
91
    }
92
93
    @Override
94
    public void setDataSource(FileDescriptor fd)
95
            throws IOException, IllegalArgumentException, IllegalStateException {
96
        mInternalMediaPlayer.setDataSource(fd);
97
    }
98
99
    @Override
100
    public void setDataSource(String path) throws IOException,
101
            IllegalArgumentException, SecurityException, IllegalStateException {
102
        mDataSource = path;
103
104
        Uri uri = Uri.parse(path);
105
        String scheme = uri.getScheme();
106
        if (!TextUtils.isEmpty(scheme) && scheme.equalsIgnoreCase("file")) {
107
            mInternalMediaPlayer.setDataSource(uri.getPath());
108
        } else {
109
            mInternalMediaPlayer.setDataSource(path);
110
        }
111
    }
112
113
    @TargetApi(Build.VERSION_CODES.M)
114
    @Override
115
    public void setDataSource(IMediaDataSource mediaDataSource) {
116
        releaseMediaDataSource();
117
118
        mMediaDataSource = new MediaDataSourceProxy(mediaDataSource);
119
        mInternalMediaPlayer.setDataSource(mMediaDataSource);
120
    }
121
122
    @TargetApi(Build.VERSION_CODES.M)
123
    private static class MediaDataSourceProxy extends MediaDataSource {
124
        private final IMediaDataSource mMediaDataSource;
125
126
        public MediaDataSourceProxy(IMediaDataSource mediaDataSource) {
127
            mMediaDataSource = mediaDataSource;
128
        }
129
130
        @Override
131
        public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
132
            return mMediaDataSource.readAt(position, buffer, offset, size);
133
        }
134
135
        @Override
136
        public long getSize() throws IOException {
137
            return mMediaDataSource.getSize();
138
        }
139
140
        @Override
141
        public void close() throws IOException {
142
            mMediaDataSource.close();
143
        }
144
    }
145
146
    @Override
147
    public String getDataSource() {
148
        return mDataSource;
149
    }
150
151
    private void releaseMediaDataSource() {
152
        if (mMediaDataSource != null) {
153
            try {
154
                mMediaDataSource.close();
155
            } catch (IOException e) {
156
                e.printStackTrace();
157
            }
158
            mMediaDataSource = null;
159
        }
160
    }
161
162
    @Override
163
    public void prepareAsync() throws IllegalStateException {
164
        mInternalMediaPlayer.prepareAsync();
165
    }
166
167
    @Override
168
    public void start() throws IllegalStateException {
169
        mInternalMediaPlayer.start();
170
    }
171
172
    @Override
173
    public void stop() throws IllegalStateException {
174
        mInternalMediaPlayer.stop();
175
    }
176
177
    @Override
178
    public void pause() throws IllegalStateException {
179
        mInternalMediaPlayer.pause();
180
    }
181
182
    @Override
183
    public void setScreenOnWhilePlaying(boolean screenOn) {
184
        mInternalMediaPlayer.setScreenOnWhilePlaying(screenOn);
185
    }
186
187
    @Override
188
    public ITrackInfo[] getTrackInfo() {
189
        return AndroidTrackInfo.fromMediaPlayer(mInternalMediaPlayer);
190
    }
191
192
    @Override
193
    public int getVideoWidth() {
194
        return mInternalMediaPlayer.getVideoWidth();
195
    }
196
197
    @Override
198
    public int getVideoHeight() {
199
        return mInternalMediaPlayer.getVideoHeight();
200
    }
201
202
    @Override
203
    public int getVideoSarNum() {
204
        return 1;
205
    }
206
207
    @Override
208
    public int getVideoSarDen() {
209
        return 1;
210
    }
211
212
    @Override
213
    public boolean isPlaying() {
214
        try {
215
            return mInternalMediaPlayer.isPlaying();
216
        } catch (IllegalStateException e) {
217
            DebugLog.printStackTrace(e);
218
            return false;
219
        }
220
    }
221
222
    @Override
223
    public void seekTo(long msec) throws IllegalStateException {
224
        mInternalMediaPlayer.seekTo((int) msec);
225
    }
226
227
    @Override
228
    public long getCurrentPosition() {
229
        try {
230
            return mInternalMediaPlayer.getCurrentPosition();
231
        } catch (IllegalStateException e) {
232
            DebugLog.printStackTrace(e);
233
            return 0;
234
        }
235
    }
236
237
    @Override
238
    public long getDuration() {
239
        try {
240
            return mInternalMediaPlayer.getDuration();
241
        } catch (IllegalStateException e) {
242
            DebugLog.printStackTrace(e);
243
            return 0;
244
        }
245
    }
246
247
    @Override
248
    public void release() {
249
        mIsReleased = true;
250
        mInternalMediaPlayer.release();
251
        releaseMediaDataSource();
252
        resetListeners();
253
        attachInternalListeners();
254
    }
255
256
    @Override
257
    public void reset() {
258
        try {
259
            mInternalMediaPlayer.reset();
260
        } catch (IllegalStateException e) {
261
            DebugLog.printStackTrace(e);
262
        }
263
        releaseMediaDataSource();
264
        resetListeners();
265
        attachInternalListeners();
266
    }
267
268
    @Override
269
    public void setLooping(boolean looping) {
270
        mInternalMediaPlayer.setLooping(looping);
271
    }
272
273
    @Override
274
    public boolean isLooping() {
275
        return mInternalMediaPlayer.isLooping();
276
    }
277
278
    @Override
279
    public void setVolume(float leftVolume, float rightVolume) {
280
        mInternalMediaPlayer.setVolume(leftVolume, rightVolume);
281
    }
282
283
    @Override
284
    public int getAudioSessionId() {
285
        return mInternalMediaPlayer.getAudioSessionId();
286
    }
287
288
    @Override
289
    public MediaInfo getMediaInfo() {
290
        if (sMediaInfo == null) {
291
            MediaInfo module = new MediaInfo();
292
293
            module.mVideoDecoder = "android";
294
            module.mVideoDecoderImpl = "HW";
295
296
            module.mAudioDecoder = "android";
297
            module.mAudioDecoderImpl = "HW";
298
299
            sMediaInfo = module;
300
        }
301
302
        return sMediaInfo;
303
    }
304
305
    @Override
306
    public void setLogEnabled(boolean enable) {
307
    }
308
309
    @Override
310
    public boolean isPlayable() {
311
        return true;
312
    }
313
314
    /*--------------------
315
     * misc
316
     */
317
    @Override
318
    public void setWakeMode(Context context, int mode) {
319
        mInternalMediaPlayer.setWakeMode(context, mode);
320
    }
321
322
    @Override
323
    public void setAudioStreamType(int streamtype) {
324
        mInternalMediaPlayer.setAudioStreamType(streamtype);
325
    }
326
327
    @Override
328
    public void setKeepInBackground(boolean keepInBackground) {
329
    }
330
331
    /*--------------------
332
     * Listeners adapter
333
     */
334
    private void attachInternalListeners() {
335
        mInternalMediaPlayer.setOnPreparedListener(mInternalListenerAdapter);
336
        mInternalMediaPlayer
337
                .setOnBufferingUpdateListener(mInternalListenerAdapter);
338
        mInternalMediaPlayer.setOnCompletionListener(mInternalListenerAdapter);
339
        mInternalMediaPlayer
340
                .setOnSeekCompleteListener(mInternalListenerAdapter);
341
        mInternalMediaPlayer
342
                .setOnVideoSizeChangedListener(mInternalListenerAdapter);
343
        mInternalMediaPlayer.setOnErrorListener(mInternalListenerAdapter);
344
        mInternalMediaPlayer.setOnInfoListener(mInternalListenerAdapter);
345
    }
346
347
    private class AndroidMediaPlayerListenerHolder implements
348
            MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener,
349
            MediaPlayer.OnBufferingUpdateListener,
350
            MediaPlayer.OnSeekCompleteListener,
351
            MediaPlayer.OnVideoSizeChangedListener,
352
            MediaPlayer.OnErrorListener, MediaPlayer.OnInfoListener {
353
        public final WeakReference<AndroidMediaPlayer> mWeakMediaPlayer;
354
355
        public AndroidMediaPlayerListenerHolder(AndroidMediaPlayer mp) {
356
            mWeakMediaPlayer = new WeakReference<AndroidMediaPlayer>(mp);
357
        }
358
359
        @Override
360
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
361
            AndroidMediaPlayer self = mWeakMediaPlayer.get();
362
            return self != null && notifyOnInfo(what, extra);
363
364
        }
365
366
        @Override
367
        public boolean onError(MediaPlayer mp, int what, int extra) {
368
            AndroidMediaPlayer self = mWeakMediaPlayer.get();
369
            return self != null && notifyOnError(what, extra);
370
371
        }
372
373
        @Override
374
        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
375
            AndroidMediaPlayer self = mWeakMediaPlayer.get();
376
            if (self == null)
377
                return;
378
379
            notifyOnVideoSizeChanged(width, height, 1, 1);
380
        }
381
382
        @Override
383
        public void onSeekComplete(MediaPlayer mp) {
384
            AndroidMediaPlayer self = mWeakMediaPlayer.get();
385
            if (self == null)
386
                return;
387
388
            notifyOnSeekComplete();
389
        }
390
391
        @Override
392
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
393
            AndroidMediaPlayer self = mWeakMediaPlayer.get();
394
            if (self == null)
395
                return;
396
397
            notifyOnBufferingUpdate(percent);
398
        }
399
400
        @Override
401
        public void onCompletion(MediaPlayer mp) {
402
            AndroidMediaPlayer self = mWeakMediaPlayer.get();
403
            if (self == null)
404
                return;
405
406
            notifyOnCompletion();
407
        }
408
409
        @Override
410
        public void onPrepared(MediaPlayer mp) {
411
            AndroidMediaPlayer self = mWeakMediaPlayer.get();
412
            if (self == null)
413
                return;
414
415
            notifyOnPrepared();
416
        }
417
    }
418
}

+ 200 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IMediaPlayer.java

@ -0,0 +1,200 @@
1
/*
2
 * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
import android.annotation.TargetApi;
20
import android.content.Context;
21
import android.net.Uri;
22
import android.os.Build;
23
import android.view.Surface;
24
import android.view.SurfaceHolder;
25
26
import java.io.FileDescriptor;
27
import java.io.IOException;
28
import java.util.Map;
29
30
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
31
import tv.danmaku.ijk.media.player.misc.ITrackInfo;
32
33
public interface IMediaPlayer {
34
    /*
35
     * Do not change these values without updating their counterparts in native
36
     */
37
    int MEDIA_INFO_UNKNOWN = 1;
38
    int MEDIA_INFO_STARTED_AS_NEXT = 2;
39
    int MEDIA_INFO_VIDEO_RENDERING_START = 3;
40
    int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;
41
    int MEDIA_INFO_BUFFERING_START = 701;
42
    int MEDIA_INFO_BUFFERING_END = 702;
43
    int MEDIA_INFO_NETWORK_BANDWIDTH = 703;
44
    int MEDIA_INFO_BAD_INTERLEAVING = 800;
45
    int MEDIA_INFO_NOT_SEEKABLE = 801;
46
    int MEDIA_INFO_METADATA_UPDATE = 802;
47
    int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
48
    int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;
49
    int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;
50
51
    int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;
52
    int MEDIA_INFO_AUDIO_RENDERING_START = 10002;
53
54
    int MEDIA_ERROR_UNKNOWN = 1;
55
    int MEDIA_ERROR_SERVER_DIED = 100;
56
    int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;
57
    int MEDIA_ERROR_IO = -1004;
58
    int MEDIA_ERROR_MALFORMED = -1007;
59
    int MEDIA_ERROR_UNSUPPORTED = -1010;
60
    int MEDIA_ERROR_TIMED_OUT = -110;
61
62
    void setDisplay(SurfaceHolder sh);
63
64
    void setDataSource(Context context, Uri uri)
65
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
66
67
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
68
    void setDataSource(Context context, Uri uri, Map<String, String> headers)
69
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
70
71
    void setDataSource(FileDescriptor fd)
72
            throws IOException, IllegalArgumentException, IllegalStateException;
73
74
    void setDataSource(String path)
75
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
76
77
    String getDataSource();
78
79
    void prepareAsync() throws IllegalStateException;
80
81
    void start() throws IllegalStateException;
82
83
    void stop() throws IllegalStateException;
84
85
    void pause() throws IllegalStateException;
86
87
    void setScreenOnWhilePlaying(boolean screenOn);
88
89
    int getVideoWidth();
90
91
    int getVideoHeight();
92
93
    boolean isPlaying();
94
95
    void seekTo(long msec) throws IllegalStateException;
96
97
    long getCurrentPosition();
98
99
    long getDuration();
100
101
    void release();
102
103
    void reset();
104
105
    void setVolume(float leftVolume, float rightVolume);
106
107
    int getAudioSessionId();
108
109
    MediaInfo getMediaInfo();
110
111
    @SuppressWarnings("EmptyMethod")
112
    @Deprecated
113
    void setLogEnabled(boolean enable);
114
115
    @Deprecated
116
    boolean isPlayable();
117
118
    void setOnPreparedListener(OnPreparedListener listener);
119
120
    void setOnCompletionListener(OnCompletionListener listener);
121
122
    void setOnBufferingUpdateListener(
123
            OnBufferingUpdateListener listener);
124
125
    void setOnSeekCompleteListener(
126
            OnSeekCompleteListener listener);
127
128
    void setOnVideoSizeChangedListener(
129
            OnVideoSizeChangedListener listener);
130
131
    void setOnErrorListener(OnErrorListener listener);
132
133
    void setOnInfoListener(OnInfoListener listener);
134
135
    /*--------------------
136
     * Listeners
137
     */
138
    interface OnPreparedListener {
139
        void onPrepared(IMediaPlayer mp);
140
    }
141
142
    interface OnCompletionListener {
143
        void onCompletion(IMediaPlayer mp);
144
    }
145
146
    interface OnBufferingUpdateListener {
147
        void onBufferingUpdate(IMediaPlayer mp, int percent);
148
    }
149
150
    interface OnSeekCompleteListener {
151
        void onSeekComplete(IMediaPlayer mp);
152
    }
153
154
    interface OnVideoSizeChangedListener {
155
        void onVideoSizeChanged(IMediaPlayer mp, int width, int height,
156
                                int sar_num, int sar_den);
157
    }
158
159
    interface OnErrorListener {
160
        boolean onError(IMediaPlayer mp, int what, int extra);
161
    }
162
163
    interface OnInfoListener {
164
        boolean onInfo(IMediaPlayer mp, int what, int extra);
165
    }
166
167
    /*--------------------
168
     * Optional
169
     */
170
    void setAudioStreamType(int streamtype);
171
172
    @Deprecated
173
    void setKeepInBackground(boolean keepInBackground);
174
175
    int getVideoSarNum();
176
177
    int getVideoSarDen();
178
179
    @Deprecated
180
    void setWakeMode(Context context, int mode);
181
182
    void setLooping(boolean looping);
183
184
    boolean isLooping();
185
186
    /*--------------------
187
     * AndroidMediaPlayer: JELLY_BEAN
188
     */
189
    ITrackInfo[] getTrackInfo();
190
191
    /*--------------------
192
     * AndroidMediaPlayer: ICE_CREAM_SANDWICH:
193
     */
194
    void setSurface(Surface surface);
195
196
    /*--------------------
197
     * AndroidMediaPlayer: M:
198
     */
199
    void setDataSource(IMediaDataSource mediaDataSource);
200
}

+ 27 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHolder.java

@ -0,0 +1,27 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
import android.graphics.SurfaceTexture;
20
21
public interface ISurfaceTextureHolder {
22
    void setSurfaceTexture(SurfaceTexture surfaceTexture);
23
24
    SurfaceTexture getSurfaceTexture();
25
26
    void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost);
27
}

+ 23 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ISurfaceTextureHost.java

@ -0,0 +1,23 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
import android.graphics.SurfaceTexture;
20
21
public interface ISurfaceTextureHost {
22
    void releaseSurfaceTexture(SurfaceTexture surfaceTexture);
23
}

+ 22 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkLibLoader.java

@ -0,0 +1,22 @@
1
/*
2
 * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
public interface IjkLibLoader {
20
    void loadLibrary(String libName) throws UnsatisfiedLinkError,
21
            SecurityException;
22
}

+ 293 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaCodecInfo.java

@ -0,0 +1,293 @@
1
package tv.danmaku.ijk.media.player;
2
3
import android.annotation.TargetApi;
4
import android.media.MediaCodecInfo;
5
import android.media.MediaCodecInfo.CodecCapabilities;
6
import android.media.MediaCodecInfo.CodecProfileLevel;
7
import android.os.Build;
8
import android.text.TextUtils;
9
import android.util.Log;
10
11
import java.util.Locale;
12
import java.util.Map;
13
import java.util.TreeMap;
14
15
public class IjkMediaCodecInfo {
16
    private final static String TAG = "IjkMediaCodecInfo";
17
18
    public static int RANK_MAX = 1000;
19
    public static final int RANK_TESTED = 800;
20
    public static final int RANK_ACCEPTABLE = 700;
21
    public static final int RANK_LAST_CHANCE = 600;
22
    public static final int RANK_SECURE = 300;
23
    public static final int RANK_SOFTWARE = 200;
24
    public static final int RANK_NON_STANDARD = 100;
25
    public static final int RANK_NO_SENSE = 0;
26
27
    public MediaCodecInfo mCodecInfo;
28
    public int mRank = 0;
29
    public String mMimeType;
30
31
    private static Map<String, Integer> sKnownCodecList;
32
33
    private static synchronized Map<String, Integer> getKnownCodecList() {
34
        if (sKnownCodecList != null)
35
            return sKnownCodecList;
36
37
        sKnownCodecList = new TreeMap<String, Integer>(
38
                String.CASE_INSENSITIVE_ORDER);
39
40
        // ----- Nvidia -----
41
        // Tegra3
42
        // Nexus 7 (2012)
43
        // Tegra K1
44
        // Nexus 9
45
        sKnownCodecList.put("OMX.Nvidia.h264.decode", RANK_TESTED);
46
        sKnownCodecList.put("OMX.Nvidia.h264.decode.secure", RANK_SECURE);
47
48
        // ----- Intel -----
49
        // Atom Z3735
50
        // Teclast X98 Air
51
        sKnownCodecList.put("OMX.Intel.hw_vd.h264", RANK_TESTED + 1);
52
        // Atom Z2560
53
        // Dell Venue 7 3730
54
        sKnownCodecList.put("OMX.Intel.VideoDecoder.AVC", RANK_TESTED);
55
56
        // ----- Qualcomm -----
57
        // MSM8260
58
        // Xiaomi MI 1S
59
        sKnownCodecList.put("OMX.qcom.video.decoder.avc", RANK_TESTED);
60
        sKnownCodecList.put("OMX.ittiam.video.decoder.avc", RANK_NO_SENSE);
61
62
        // ----- Samsung -----
63
        // Exynos 3110
64
        // Nexus S
65
        sKnownCodecList.put("OMX.SEC.avc.dec", RANK_TESTED);
66
        sKnownCodecList.put("OMX.SEC.AVC.Decoder", RANK_TESTED - 1);
67
        // OMX.SEC.avcdec doesn't reorder output pictures on GT-9100
68
        sKnownCodecList.put("OMX.SEC.avcdec", RANK_TESTED - 2);
69
        sKnownCodecList.put("OMX.SEC.avc.sw.dec", RANK_SOFTWARE);
70
        // Exynos 5 ?
71
        sKnownCodecList.put("OMX.Exynos.avc.dec", RANK_TESTED);
72
        sKnownCodecList.put("OMX.Exynos.AVC.Decoder", RANK_TESTED - 1);
73
74
        // ------ Huawei hisilicon ------
75
        // Kirin 910, Mali 450 MP
76
        // Huawei HONOR 3C (H30-L01)
77
        sKnownCodecList.put("OMX.k3.video.decoder.avc", RANK_TESTED);
78
        // Kirin 920, Mali T624
79
        // Huawei HONOR 6
80
        sKnownCodecList.put("OMX.IMG.MSVDX.Decoder.AVC", RANK_TESTED);
81
82
        // ----- TI -----
83
        // TI OMAP4460
84
        // Galaxy Nexus
85
        sKnownCodecList.put("OMX.TI.DUCATI1.VIDEO.DECODER", RANK_TESTED);
86
87
        // ------ RockChip ------
88
        // Youku TVBox
89
        sKnownCodecList.put("OMX.rk.video_decoder.avc", RANK_TESTED);
90
91
        // ------ AMLogic -----
92
        // MiBox1, 1s, 2
93
        sKnownCodecList.put("OMX.amlogic.avc.decoder.awesome", RANK_TESTED);
94
95
        // ------ Marvell ------
96
        // Lenovo A788t
97
        sKnownCodecList.put("OMX.MARVELL.VIDEO.HW.CODA7542DECODER", RANK_TESTED);
98
        sKnownCodecList.put("OMX.MARVELL.VIDEO.H264DECODER", RANK_SOFTWARE);
99
100
        // ----- TODO: need test -----
101
        sKnownCodecList.remove("OMX.Action.Video.Decoder");
102
        sKnownCodecList.remove("OMX.allwinner.video.decoder.avc");
103
        sKnownCodecList.remove("OMX.BRCM.vc4.decoder.avc");
104
        sKnownCodecList.remove("OMX.brcm.video.h264.hw.decoder");
105
        sKnownCodecList.remove("OMX.brcm.video.h264.decoder");
106
        sKnownCodecList.remove("OMX.cosmo.video.decoder.avc");
107
        sKnownCodecList.remove("OMX.duos.h264.decoder");
108
        sKnownCodecList.remove("OMX.hantro.81x0.video.decoder");
109
        sKnownCodecList.remove("OMX.hantro.G1.video.decoder");
110
        sKnownCodecList.remove("OMX.hisi.video.decoder");
111
        sKnownCodecList.remove("OMX.LG.decoder.video.avc");
112
        sKnownCodecList.remove("OMX.MS.AVC.Decoder");
113
        sKnownCodecList.remove("OMX.RENESAS.VIDEO.DECODER.H264");
114
        sKnownCodecList.remove("OMX.RTK.video.decoder");
115
        sKnownCodecList.remove("OMX.sprd.h264.decoder");
116
        sKnownCodecList.remove("OMX.ST.VFM.H264Dec");
117
        sKnownCodecList.remove("OMX.vpu.video_decoder.avc");
118
        sKnownCodecList.remove("OMX.WMT.decoder.avc");
119
120
        // Really ?
121
        sKnownCodecList.remove("OMX.bluestacks.hw.decoder");
122
123
        // ---------------
124
        // Useless codec
125
        // ----- google -----
126
        sKnownCodecList.put("OMX.google.h264.decoder", RANK_SOFTWARE);
127
        sKnownCodecList.put("OMX.google.h264.lc.decoder", RANK_SOFTWARE);
128
        // ----- huawei k920 -----
129
        sKnownCodecList.put("OMX.k3.ffmpeg.decoder", RANK_SOFTWARE);
130
        sKnownCodecList.put("OMX.ffmpeg.video.decoder", RANK_SOFTWARE);
131
        // ----- unknown -----
132
        sKnownCodecList.put("OMX.sprd.soft.h264.decoder", RANK_SOFTWARE);
133
134
        return sKnownCodecList;
135
    }
136
137
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
138
    public static IjkMediaCodecInfo setupCandidate(MediaCodecInfo codecInfo,
139
            String mimeType) {
140
        if (codecInfo == null
141
                || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
142
            return null;
143
144
        String name = codecInfo.getName();
145
        if (TextUtils.isEmpty(name))
146
            return null;
147
148
        name = name.toLowerCase(Locale.US);
149
        int rank = RANK_NO_SENSE;
150
        if (!name.startsWith("omx.")) {
151
            rank = RANK_NON_STANDARD;
152
        } else if (name.startsWith("omx.pv")) {
153
            rank = RANK_SOFTWARE;
154
        } else if (name.startsWith("omx.google.")) {
155
            rank = RANK_SOFTWARE;
156
        } else if (name.startsWith("omx.ffmpeg.")) {
157
            rank = RANK_SOFTWARE;
158
        } else if (name.startsWith("omx.k3.ffmpeg.")) {
159
            rank = RANK_SOFTWARE;
160
        } else if (name.startsWith("omx.avcodec.")) {
161
            rank = RANK_SOFTWARE;
162
        } else if (name.startsWith("omx.ittiam.")) {
163
            // unknown codec in qualcomm SoC
164
            rank = RANK_NO_SENSE;
165
        } else if (name.startsWith("omx.mtk.")) {
166
            // 1. MTK only works on 4.3 and above
167
            // 2. MTK works on MIUI 6 (4.2.1)
168
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
169
                rank = RANK_NO_SENSE;
170
            else
171
                rank = RANK_TESTED;
172
        } else {
173
            Integer knownRank = getKnownCodecList().get(name);
174
            if (knownRank != null) {
175
                rank = knownRank;
176
            } else {
177
                try {
178
                    CodecCapabilities cap = codecInfo
179
                            .getCapabilitiesForType(mimeType);
180
                    if (cap != null)
181
                        rank = RANK_ACCEPTABLE;
182
                    else
183
                        rank = RANK_LAST_CHANCE;
184
                } catch (Throwable e) {
185
                    rank = RANK_LAST_CHANCE;
186
                }
187
            }
188
        }
189
190
        IjkMediaCodecInfo candidate = new IjkMediaCodecInfo();
191
        candidate.mCodecInfo = codecInfo;
192
        candidate.mRank = rank;
193
        candidate.mMimeType = mimeType;
194
        return candidate;
195
    }
196
197
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
198
    public void dumpProfileLevels(String mimeType) {
199
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
200
            return;
201
202
        try {
203
            CodecCapabilities caps = mCodecInfo
204
                    .getCapabilitiesForType(mimeType);
205
            int maxProfile = 0;
206
            int maxLevel = 0;
207
            if (caps != null) {
208
                if (caps.profileLevels != null) {
209
                    for (CodecProfileLevel profileLevel : caps.profileLevels) {
210
                        if (profileLevel == null)
211
                            continue;
212
213
                        maxProfile = Math.max(maxProfile, profileLevel.profile);
214
                        maxLevel = Math.max(maxLevel, profileLevel.level);
215
                    }
216
                }
217
            }
218
219
            Log.i(TAG,
220
                    String.format(Locale.US, "%s",
221
                            getProfileLevelName(maxProfile, maxLevel)));
222
        } catch (Throwable e) {
223
            Log.i(TAG, "profile-level: exception");
224
        }
225
    }
226
227
    public static String getProfileLevelName(int profile, int level) {
228
        return String.format(Locale.US, " %s Profile Level %s (%d,%d)",
229
                getProfileName(profile), getLevelName(level), profile, level);
230
    }
231
232
    public static String getProfileName(int profile) {
233
        switch (profile) {
234
        case CodecProfileLevel.AVCProfileBaseline:
235
            return "Baseline";
236
        case CodecProfileLevel.AVCProfileMain:
237
            return "Main";
238
        case CodecProfileLevel.AVCProfileExtended:
239
            return "Extends";
240
        case CodecProfileLevel.AVCProfileHigh:
241
            return "High";
242
        case CodecProfileLevel.AVCProfileHigh10:
243
            return "High10";
244
        case CodecProfileLevel.AVCProfileHigh422:
245
            return "High422";
246
        case CodecProfileLevel.AVCProfileHigh444:
247
            return "High444";
248
        default:
249
            return "Unknown";
250
        }
251
    }
252
253
    public static String getLevelName(int level) {
254
        switch (level) {
255
        case CodecProfileLevel.AVCLevel1:
256
            return "1";
257
        case CodecProfileLevel.AVCLevel1b:
258
            return "1b";
259
        case CodecProfileLevel.AVCLevel11:
260
            return "11";
261
        case CodecProfileLevel.AVCLevel12:
262
            return "12";
263
        case CodecProfileLevel.AVCLevel13:
264
            return "13";
265
        case CodecProfileLevel.AVCLevel2:
266
            return "2";
267
        case CodecProfileLevel.AVCLevel21:
268
            return "21";
269
        case CodecProfileLevel.AVCLevel22:
270
            return "22";
271
        case CodecProfileLevel.AVCLevel3:
272
            return "3";
273
        case CodecProfileLevel.AVCLevel31:
274
            return "31";
275
        case CodecProfileLevel.AVCLevel32:
276
            return "32";
277
        case CodecProfileLevel.AVCLevel4:
278
            return "4";
279
        case CodecProfileLevel.AVCLevel41:
280
            return "41";
281
        case CodecProfileLevel.AVCLevel42:
282
            return "42";
283
        case CodecProfileLevel.AVCLevel5:
284
            return "5";
285
        case CodecProfileLevel.AVCLevel51:
286
            return "51";
287
        case 65536: // CodecProfileLevel.AVCLevel52:
288
            return "52";
289
        default:
290
            return "0";
291
        }
292
    }
293
}

+ 380 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaMeta.java

@ -0,0 +1,380 @@
1
package tv.danmaku.ijk.media.player;
2
3
import android.os.Bundle;
4
import android.text.TextUtils;
5
6
import java.util.ArrayList;
7
import java.util.Locale;
8
9
@SuppressWarnings("SameParameterValue")
10
public class IjkMediaMeta {
11
    // media meta
12
    public static final String IJKM_KEY_FORMAT = "format";
13
    public static final String IJKM_KEY_DURATION_US = "duration_us";
14
    public static final String IJKM_KEY_START_US = "start_us";
15
    public static final String IJKM_KEY_BITRATE = "bitrate";
16
    public static final String IJKM_KEY_VIDEO_STREAM = "video";
17
    public static final String IJKM_KEY_AUDIO_STREAM = "audio";
18
19
    // stream meta
20
    public static final String IJKM_KEY_TYPE = "type";
21
    public static final String IJKM_VAL_TYPE__VIDEO = "video";
22
    public static final String IJKM_VAL_TYPE__AUDIO = "audio";
23
    public static final String IJKM_VAL_TYPE__UNKNOWN = "unknown";
24
    public static final String IJKM_KEY_LANGUAGE = "language";
25
26
    public static final String IJKM_KEY_CODEC_NAME = "codec_name";
27
    public static final String IJKM_KEY_CODEC_PROFILE = "codec_profile";
28
    public static final String IJKM_KEY_CODEC_LEVEL = "codec_level";
29
    public static final String IJKM_KEY_CODEC_LONG_NAME = "codec_long_name";
30
    public static final String IJKM_KEY_CODEC_PIXEL_FORMAT = "codec_pixel_format";
31
32
    // stream: video
33
    public static final String IJKM_KEY_WIDTH = "width";
34
    public static final String IJKM_KEY_HEIGHT = "height";
35
    public static final String IJKM_KEY_FPS_NUM = "fps_num";
36
    public static final String IJKM_KEY_FPS_DEN = "fps_den";
37
    public static final String IJKM_KEY_TBR_NUM = "tbr_num";
38
    public static final String IJKM_KEY_TBR_DEN = "tbr_den";
39
    public static final String IJKM_KEY_SAR_NUM = "sar_num";
40
    public static final String IJKM_KEY_SAR_DEN = "sar_den";
41
    // stream: audio
42
    public static final String IJKM_KEY_SAMPLE_RATE = "sample_rate";
43
    public static final String IJKM_KEY_CHANNEL_LAYOUT = "channel_layout";
44
45
    public static final String IJKM_KEY_STREAMS = "streams";
46
47
    public static final long AV_CH_FRONT_LEFT = 0x00000001;
48
    public static final long AV_CH_FRONT_RIGHT = 0x00000002;
49
    public static final long AV_CH_FRONT_CENTER = 0x00000004;
50
    public static final long AV_CH_LOW_FREQUENCY = 0x00000008;
51
    public static final long AV_CH_BACK_LEFT = 0x00000010;
52
    public static final long AV_CH_BACK_RIGHT = 0x00000020;
53
    public static final long AV_CH_FRONT_LEFT_OF_CENTER = 0x00000040;
54
    public static final long AV_CH_FRONT_RIGHT_OF_CENTER = 0x00000080;
55
    public static final long AV_CH_BACK_CENTER = 0x00000100;
56
    public static final long AV_CH_SIDE_LEFT = 0x00000200;
57
    public static final long AV_CH_SIDE_RIGHT = 0x00000400;
58
    public static final long AV_CH_TOP_CENTER = 0x00000800;
59
    public static final long AV_CH_TOP_FRONT_LEFT = 0x00001000;
60
    public static final long AV_CH_TOP_FRONT_CENTER = 0x00002000;
61
    public static final long AV_CH_TOP_FRONT_RIGHT = 0x00004000;
62
    public static final long AV_CH_TOP_BACK_LEFT = 0x00008000;
63
    public static final long AV_CH_TOP_BACK_CENTER = 0x00010000;
64
    public static final long AV_CH_TOP_BACK_RIGHT = 0x00020000;
65
    public static final long AV_CH_STEREO_LEFT = 0x20000000;
66
    public static final long AV_CH_STEREO_RIGHT = 0x40000000;
67
    public static final long AV_CH_WIDE_LEFT = 0x0000000080000000L;
68
    public static final long AV_CH_WIDE_RIGHT = 0x0000000100000000L;
69
    public static final long AV_CH_SURROUND_DIRECT_LEFT = 0x0000000200000000L;
70
    public static final long AV_CH_SURROUND_DIRECT_RIGHT = 0x0000000400000000L;
71
    public static final long AV_CH_LOW_FREQUENCY_2 = 0x0000000800000000L;
72
73
    public static final long AV_CH_LAYOUT_MONO = (AV_CH_FRONT_CENTER);
74
    public static final long AV_CH_LAYOUT_STEREO = (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT);
75
    public static final long AV_CH_LAYOUT_2POINT1 = (AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY);
76
    public static final long AV_CH_LAYOUT_2_1 = (AV_CH_LAYOUT_STEREO | AV_CH_BACK_CENTER);
77
    public static final long AV_CH_LAYOUT_SURROUND = (AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER);
78
    public static final long AV_CH_LAYOUT_3POINT1 = (AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY);
79
    public static final long AV_CH_LAYOUT_4POINT0 = (AV_CH_LAYOUT_SURROUND | AV_CH_BACK_CENTER);
80
    public static final long AV_CH_LAYOUT_4POINT1 = (AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY);
81
    public static final long AV_CH_LAYOUT_2_2 = (AV_CH_LAYOUT_STEREO
82
            | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT);
83
    public static final long AV_CH_LAYOUT_QUAD = (AV_CH_LAYOUT_STEREO
84
            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
85
    public static final long AV_CH_LAYOUT_5POINT0 = (AV_CH_LAYOUT_SURROUND
86
            | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT);
87
    public static final long AV_CH_LAYOUT_5POINT1 = (AV_CH_LAYOUT_5POINT0 | AV_CH_LOW_FREQUENCY);
88
    public static final long AV_CH_LAYOUT_5POINT0_BACK = (AV_CH_LAYOUT_SURROUND
89
            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
90
    public static final long AV_CH_LAYOUT_5POINT1_BACK = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_LOW_FREQUENCY);
91
    public static final long AV_CH_LAYOUT_6POINT0 = (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_CENTER);
92
    public static final long AV_CH_LAYOUT_6POINT0_FRONT = (AV_CH_LAYOUT_2_2
93
            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
94
    public static final long AV_CH_LAYOUT_HEXAGONAL = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_BACK_CENTER);
95
    public static final long AV_CH_LAYOUT_6POINT1 = (AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER);
96
    public static final long AV_CH_LAYOUT_6POINT1_BACK = (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_BACK_CENTER);
97
    public static final long AV_CH_LAYOUT_6POINT1_FRONT = (AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_LOW_FREQUENCY);
98
    public static final long AV_CH_LAYOUT_7POINT0 = (AV_CH_LAYOUT_5POINT0
99
            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
100
    public static final long AV_CH_LAYOUT_7POINT0_FRONT = (AV_CH_LAYOUT_5POINT0
101
            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
102
    public static final long AV_CH_LAYOUT_7POINT1 = (AV_CH_LAYOUT_5POINT1
103
            | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT);
104
    public static final long AV_CH_LAYOUT_7POINT1_WIDE = (AV_CH_LAYOUT_5POINT1
105
            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
106
    public static final long AV_CH_LAYOUT_7POINT1_WIDE_BACK = (AV_CH_LAYOUT_5POINT1_BACK
107
            | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER);
108
    public static final long AV_CH_LAYOUT_OCTAGONAL = (AV_CH_LAYOUT_5POINT0
109
            | AV_CH_BACK_LEFT | AV_CH_BACK_CENTER | AV_CH_BACK_RIGHT);
110
    public static final long AV_CH_LAYOUT_STEREO_DOWNMIX = (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT);
111
112
    public Bundle mMediaMeta;
113
114
    public String mFormat;
115
    public long mDurationUS;
116
    public long mStartUS;
117
    public long mBitrate;
118
119
    public final ArrayList<IjkStreamMeta> mStreams = new ArrayList<IjkStreamMeta>();
120
    public IjkStreamMeta mVideoStream;
121
    public IjkStreamMeta mAudioStream;
122
123
    public String getString(String key) {
124
        return mMediaMeta.getString(key);
125
    }
126
127
    public int getInt(String key) {
128
        return getInt(key, 0);
129
    }
130
131
    public int getInt(String key, int defaultValue) {
132
        String value = getString(key);
133
        if (TextUtils.isEmpty(value))
134
            return defaultValue;
135
136
        try {
137
            return Integer.parseInt(value);
138
        } catch (NumberFormatException e) {
139
            return defaultValue;
140
        }
141
    }
142
143
    public long getLong(String key) {
144
        return getLong(key, 0);
145
    }
146
147
    public long getLong(String key, long defaultValue) {
148
        String value = getString(key);
149
        if (TextUtils.isEmpty(value))
150
            return defaultValue;
151
152
        try {
153
            return Long.parseLong(value);
154
        } catch (NumberFormatException e) {
155
            return defaultValue;
156
        }
157
    }
158
159
    public ArrayList<Bundle> getParcelableArrayList(String key) {
160
        return mMediaMeta.getParcelableArrayList(key);
161
    }
162
163
    public String getDurationInline() {
164
        long duration = mDurationUS + 5000;
165
        long secs = duration / 1000000;
166
        long mins = secs / 60;
167
        secs %= 60;
168
        long hours = mins / 60;
169
        mins %= 60;
170
        return String.format(Locale.US, "%02d:%02d:%02d", hours, mins, secs);
171
    }
172
173
    public static IjkMediaMeta parse(Bundle mediaMeta) {
174
        if (mediaMeta == null)
175
            return null;
176
177
        IjkMediaMeta meta = new IjkMediaMeta();
178
        meta.mMediaMeta = mediaMeta;
179
180
        meta.mFormat = meta.getString(IJKM_KEY_FORMAT);
181
        meta.mDurationUS = meta.getLong(IJKM_KEY_DURATION_US);
182
        meta.mStartUS = meta.getLong(IJKM_KEY_START_US);
183
        meta.mBitrate = meta.getLong(IJKM_KEY_BITRATE);
184
185
        int videoStreamIndex = meta.getInt(IJKM_KEY_VIDEO_STREAM, -1);
186
        int audioStreamIndex = meta.getInt(IJKM_KEY_AUDIO_STREAM, -1);
187
188
        ArrayList<Bundle> streams = meta
189
                .getParcelableArrayList(IJKM_KEY_STREAMS);
190
        if (streams == null)
191
            return meta;
192
193
        int index = -1;
194
        for (Bundle streamBundle : streams) {
195
            index++;
196
197
            if (streamBundle == null) {
198
                continue;
199
            }
200
201
            IjkStreamMeta streamMeta = new IjkStreamMeta(index);
202
            streamMeta.mMeta = streamBundle;
203
            streamMeta.mType = streamMeta.getString(IJKM_KEY_TYPE);
204
            streamMeta.mLanguage = streamMeta.getString(IJKM_KEY_LANGUAGE);
205
            if (TextUtils.isEmpty(streamMeta.mType))
206
                continue;
207
208
            streamMeta.mCodecName = streamMeta.getString(IJKM_KEY_CODEC_NAME);
209
            streamMeta.mCodecProfile = streamMeta
210
                    .getString(IJKM_KEY_CODEC_PROFILE);
211
            streamMeta.mCodecLongName = streamMeta
212
                    .getString(IJKM_KEY_CODEC_LONG_NAME);
213
            streamMeta.mBitrate = streamMeta.getInt(IJKM_KEY_BITRATE);
214
215
            if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__VIDEO)) {
216
                streamMeta.mWidth = streamMeta.getInt(IJKM_KEY_WIDTH);
217
                streamMeta.mHeight = streamMeta.getInt(IJKM_KEY_HEIGHT);
218
                streamMeta.mFpsNum = streamMeta.getInt(IJKM_KEY_FPS_NUM);
219
                streamMeta.mFpsDen = streamMeta.getInt(IJKM_KEY_FPS_DEN);
220
                streamMeta.mTbrNum = streamMeta.getInt(IJKM_KEY_TBR_NUM);
221
                streamMeta.mTbrDen = streamMeta.getInt(IJKM_KEY_TBR_DEN);
222
                streamMeta.mSarNum = streamMeta.getInt(IJKM_KEY_SAR_NUM);
223
                streamMeta.mSarDen = streamMeta.getInt(IJKM_KEY_SAR_DEN);
224
225
                if (videoStreamIndex == index) {
226
                    meta.mVideoStream = streamMeta;
227
                }
228
            } else if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__AUDIO)) {
229
                streamMeta.mSampleRate = streamMeta
230
                        .getInt(IJKM_KEY_SAMPLE_RATE);
231
                streamMeta.mChannelLayout = streamMeta
232
                        .getLong(IJKM_KEY_CHANNEL_LAYOUT);
233
234
                if (audioStreamIndex == index) {
235
                    meta.mAudioStream = streamMeta;
236
                }
237
            }
238
            meta.mStreams.add(streamMeta);
239
        }
240
241
        return meta;
242
    }
243
244
    public static class IjkStreamMeta {
245
        public Bundle mMeta;
246
247
        public final int mIndex;
248
        public String mType;
249
        public String mLanguage;
250
251
        // common
252
        public String mCodecName;
253
        public String mCodecProfile;
254
        public String mCodecLongName;
255
        public long mBitrate;
256
257
        // video
258
        public int mWidth;
259
        public int mHeight;
260
        public int mFpsNum;
261
        public int mFpsDen;
262
        public int mTbrNum;
263
        public int mTbrDen;
264
        public int mSarNum;
265
        public int mSarDen;
266
267
        // audio
268
        public int mSampleRate;
269
        public long mChannelLayout;
270
271
        public IjkStreamMeta(int index) {
272
            mIndex = index;
273
        }
274
275
        public String getString(String key) {
276
            return mMeta.getString(key);
277
        }
278
279
        public int getInt(String key) {
280
            return getInt(key, 0);
281
        }
282
283
        public int getInt(String key, int defaultValue) {
284
            String value = getString(key);
285
            if (TextUtils.isEmpty(value))
286
                return defaultValue;
287
288
            try {
289
                return Integer.parseInt(value);
290
            } catch (NumberFormatException e) {
291
                return defaultValue;
292
            }
293
        }
294
295
        public long getLong(String key) {
296
            return getLong(key, 0);
297
        }
298
299
        public long getLong(String key, long defaultValue) {
300
            String value = getString(key);
301
            if (TextUtils.isEmpty(value))
302
                return defaultValue;
303
304
            try {
305
                return Long.parseLong(value);
306
            } catch (NumberFormatException e) {
307
                return defaultValue;
308
            }
309
        }
310
311
        public String getCodecLongNameInline() {
312
            if (!TextUtils.isEmpty(mCodecLongName)) {
313
                return mCodecLongName;
314
            } else if (!TextUtils.isEmpty(mCodecName)) {
315
                return mCodecName;
316
            } else {
317
                return "N/A";
318
            }
319
        }
320
321
        public String getCodecShortNameInline() {
322
            if (!TextUtils.isEmpty(mCodecName)) {
323
                return mCodecName;
324
            } else {
325
                return "N/A";
326
            }
327
        }
328
329
        public String getResolutionInline() {
330
            if (mWidth <= 0 || mHeight <= 0) {
331
                return "N/A";
332
            } else if (mSarNum <= 0 || mSarDen <= 0) {
333
                return String.format(Locale.US, "%d x %d", mWidth, mHeight);
334
            } else {
335
                return String.format(Locale.US, "%d x %d [SAR %d:%d]", mWidth,
336
                        mHeight, mSarNum, mSarDen);
337
            }
338
        }
339
340
        public String getFpsInline() {
341
            if (mFpsNum <= 0 || mFpsDen <= 0) {
342
                return "N/A";
343
            } else {
344
                return String.valueOf(((float) (mFpsNum)) / mFpsDen);
345
            }
346
        }
347
348
        public String getBitrateInline() {
349
            if (mBitrate <= 0) {
350
                return "N/A";
351
            } else if (mBitrate < 1000) {
352
                return String.format(Locale.US, "%d bit/s", mBitrate);
353
            } else {
354
                return String.format(Locale.US, "%d kb/s", mBitrate / 1000);
355
            }
356
        }
357
358
        public String getSampleRateInline() {
359
            if (mSampleRate <= 0) {
360
                return "N/A";
361
            } else {
362
                return String.format(Locale.US, "%d Hz", mSampleRate);
363
            }
364
        }
365
366
        public String getChannelLayoutInline() {
367
            if (mChannelLayout <= 0) {
368
                return "N/A";
369
            } else {
370
                if (mChannelLayout == AV_CH_LAYOUT_MONO) {
371
                    return "mono";
372
                } else if (mChannelLayout == AV_CH_LAYOUT_STEREO) {
373
                    return "stereo";
374
                } else {
375
                    return String.format(Locale.US, "%x", mChannelLayout);
376
                }
377
            }
378
        }
379
    }
380
}

+ 1212 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/IjkMediaPlayer.java

@ -0,0 +1,1212 @@
1
/*
2
 * Copyright (C) 2006 The Android Open Source Project
3
 * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.com>
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
package tv.danmaku.ijk.media.player;
19
20
import android.annotation.SuppressLint;
21
import android.annotation.TargetApi;
22
import android.content.ContentResolver;
23
import android.content.Context;
24
import android.content.res.AssetFileDescriptor;
25
import android.graphics.SurfaceTexture;
26
import android.media.MediaCodecInfo;
27
import android.media.MediaCodecList;
28
import android.media.RingtoneManager;
29
import android.net.Uri;
30
import android.os.Build;
31
import android.os.Bundle;
32
import android.os.Handler;
33
import android.os.Looper;
34
import android.os.Message;
35
import android.os.ParcelFileDescriptor;
36
import android.os.PowerManager;
37
import android.provider.Settings;
38
import android.text.TextUtils;
39
import android.util.Log;
40
import android.view.Surface;
41
import android.view.SurfaceHolder;
42
43
import java.io.FileDescriptor;
44
import java.io.FileNotFoundException;
45
import java.io.IOException;
46
import java.lang.ref.WeakReference;
47
import java.lang.reflect.Field;
48
import java.security.InvalidParameterException;
49
import java.util.ArrayList;
50
import java.util.Locale;
51
import java.util.Map;
52
53
import tv.danmaku.ijk.media.player.annotations.AccessedByNative;
54
import tv.danmaku.ijk.media.player.annotations.CalledByNative;
55
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
56
import tv.danmaku.ijk.media.player.misc.ITrackInfo;
57
import tv.danmaku.ijk.media.player.misc.IjkTrackInfo;
58
import tv.danmaku.ijk.media.player.pragma.DebugLog;
59
60
/**
61
 * @author bbcallen
62
 * 
63
 *         Java wrapper of ffplay.
64
 */
65
public final class IjkMediaPlayer extends AbstractMediaPlayer {
66
    private final static String TAG = IjkMediaPlayer.class.getName();
67
68
    private static final int MEDIA_NOP = 0; // interface test message
69
    private static final int MEDIA_PREPARED = 1;
70
    private static final int MEDIA_PLAYBACK_COMPLETE = 2;
71
    private static final int MEDIA_BUFFERING_UPDATE = 3;
72
    private static final int MEDIA_SEEK_COMPLETE = 4;
73
    private static final int MEDIA_SET_VIDEO_SIZE = 5;
74
    private static final int MEDIA_TIMED_TEXT = 99;
75
    private static final int MEDIA_ERROR = 100;
76
    private static final int MEDIA_INFO = 200;
77
78
    protected static final int MEDIA_SET_VIDEO_SAR = 10001;
79
80
    //----------------------------------------
81
    // options
82
    public static final int IJK_LOG_UNKNOWN = 0;
83
    public static final int IJK_LOG_DEFAULT = 1;
84
85
    public static final int IJK_LOG_VERBOSE = 2;
86
    public static final int IJK_LOG_DEBUG = 3;
87
    public static final int IJK_LOG_INFO = 4;
88
    public static final int IJK_LOG_WARN = 5;
89
    public static final int IJK_LOG_ERROR = 6;
90
    public static final int IJK_LOG_FATAL = 7;
91
    public static final int IJK_LOG_SILENT = 8;
92
93
    public static final int OPT_CATEGORY_FORMAT     = 1;
94
    public static final int OPT_CATEGORY_CODEC      = 2;
95
    public static final int OPT_CATEGORY_SWS        = 3;
96
    public static final int OPT_CATEGORY_PLAYER     = 4;
97
98
    public static final int SDL_FCC_YV12 = 0x32315659; // YV12
99
    public static final int SDL_FCC_RV16 = 0x36315652; // RGB565
100
    public static final int SDL_FCC_RV32 = 0x32335652; // RGBX8888
101
    //----------------------------------------
102
103
    //----------------------------------------
104
    // properties
105
    public static final int PROP_FLOAT_VIDEO_DECODE_FRAMES_PER_SECOND = 10001;
106
    public static final int PROP_FLOAT_VIDEO_OUTPUT_FRAMES_PER_SECOND = 10002;
107
    public static final int FFP_PROP_FLOAT_PLAYBACK_RATE              = 10003;
108
109
    public static final int FFP_PROP_INT64_SELECTED_VIDEO_STREAM      = 20001;
110
    public static final int FFP_PROP_INT64_SELECTED_AUDIO_STREAM      = 20002;
111
112
    public static final int FFP_PROP_INT64_VIDEO_DECODER              = 20003;
113
    public static final int FFP_PROP_INT64_AUDIO_DECODER              = 20004;
114
    public static final int     FFP_PROPV_DECODER_UNKNOWN             = 0;
115
    public static final int     FFP_PROPV_DECODER_AVCODEC             = 1;
116
    public static final int     FFP_PROPV_DECODER_MEDIACODEC          = 2;
117
    public static final int     FFP_PROPV_DECODER_VIDEOTOOLBOX        = 3;
118
    public static final int FFP_PROP_INT64_VIDEO_CACHED_DURATION      = 20005;
119
    public static final int FFP_PROP_INT64_AUDIO_CACHED_DURATION      = 20006;
120
    public static final int FFP_PROP_INT64_VIDEO_CACHED_BYTES         = 20007;
121
    public static final int FFP_PROP_INT64_AUDIO_CACHED_BYTES         = 20008;
122
    public static final int FFP_PROP_INT64_VIDEO_CACHED_PACKETS       = 20009;
123
    public static final int FFP_PROP_INT64_AUDIO_CACHED_PACKETS       = 20010;
124
    public static final int FFP_PROP_INT64_BIT_RATE                   = 20100;
125
    public static final int FFP_PROP_INT64_TCP_SPEED                  = 20200;
126
    public static final int FFP_PROP_INT64_LATEST_SEEK_LOAD_DURATION  = 20300;
127
    //----------------------------------------
128
129
    @AccessedByNative
130
    private long mNativeMediaPlayer;
131
    @AccessedByNative
132
    private long mNativeMediaDataSource;
133
134
    @AccessedByNative
135
    private int mNativeSurfaceTexture;
136
137
    @AccessedByNative
138
    private int mListenerContext;
139
140
    private SurfaceHolder mSurfaceHolder;
141
    private EventHandler mEventHandler;
142
    private PowerManager.WakeLock mWakeLock = null;
143
    private boolean mScreenOnWhilePlaying;
144
    private boolean mStayAwake;
145
146
    private int mVideoWidth;
147
    private int mVideoHeight;
148
    private int mVideoSarNum;
149
    private int mVideoSarDen;
150
151
    private String mDataSource;
152
153
    /**
154
     * Default library loader
155
     * Load them by yourself, if your libraries are not installed at default place.
156
     */
157
    private static final IjkLibLoader sLocalLibLoader = new IjkLibLoader() {
158
        @Override
159
        public void loadLibrary(String libName) throws UnsatisfiedLinkError, SecurityException {
160
            System.loadLibrary(libName);
161
        }
162
    };
163
164
    private static volatile boolean mIsLibLoaded = false;
165
    public static void loadLibrariesOnce(IjkLibLoader libLoader) {
166
        synchronized (IjkMediaPlayer.class) {
167
            if (!mIsLibLoaded) {
168
                if (libLoader == null)
169
                    libLoader = sLocalLibLoader;
170
171
                libLoader.loadLibrary("ijkffmpeg");
172
                libLoader.loadLibrary("ijksdl");
173
                libLoader.loadLibrary("ijkplayer");
174
                mIsLibLoaded = true;
175
            }
176
        }
177
    }
178
179
    private static volatile boolean mIsNativeInitialized = false;
180
    private static void initNativeOnce() {
181
        synchronized (IjkMediaPlayer.class) {
182
            if (!mIsNativeInitialized) {
183
                native_init();
184
                mIsNativeInitialized = true;
185
            }
186
        }
187
    }
188
189
    /**
190
     * Default constructor. Consider using one of the create() methods for
191
     * synchronously instantiating a IjkMediaPlayer from a Uri or resource.
192
     * <p>
193
     * When done with the IjkMediaPlayer, you should call {@link #release()}, to
194
     * free the resources. If not released, too many IjkMediaPlayer instances
195
     * may result in an exception.
196
     * </p>
197
     */
198
    public IjkMediaPlayer() {
199
        this(sLocalLibLoader);
200
    }
201
202
    /**
203
     * do not loadLibaray
204
     * @param libLoader
205
     *              custom library loader, can be null.
206
     */
207
    public IjkMediaPlayer(IjkLibLoader libLoader) {
208
        initPlayer(libLoader);
209
    }
210
211
    private void initPlayer(IjkLibLoader libLoader) {
212
        loadLibrariesOnce(libLoader);
213
        initNativeOnce();
214
215
        Looper looper;
216
        if ((looper = Looper.myLooper()) != null) {
217
            mEventHandler = new EventHandler(this, looper);
218
        } else if ((looper = Looper.getMainLooper()) != null) {
219
            mEventHandler = new EventHandler(this, looper);
220
        } else {
221
            mEventHandler = null;
222
        }
223
224
        /*
225
         * Native setup requires a weak reference to our object. It's easier to
226
         * create it here than in C++.
227
         */
228
        native_setup(new WeakReference<IjkMediaPlayer>(this));
229
    }
230
231
    /*
232
     * Update the IjkMediaPlayer SurfaceTexture. Call after setting a new
233
     * display surface.
234
     */
235
    private native void _setVideoSurface(Surface surface);
236
237
    /**
238
     * Sets the {@link SurfaceHolder} to use for displaying the video portion of
239
     * the media.
240
     * 
241
     * Either a surface holder or surface must be set if a display or video sink
242
     * is needed. Not calling this method or {@link #setSurface(Surface)} when
243
     * playing back a video will result in only the audio track being played. A
244
     * null surface holder or surface will result in only the audio track being
245
     * played.
246
     * 
247
     * @param sh
248
     *            the SurfaceHolder to use for video display
249
     */
250
    @Override
251
    public void setDisplay(SurfaceHolder sh) {
252
        mSurfaceHolder = sh;
253
        Surface surface;
254
        if (sh != null) {
255
            surface = sh.getSurface();
256
        } else {
257
            surface = null;
258
        }
259
        _setVideoSurface(surface);
260
        updateSurfaceScreenOn();
261
    }
262
263
    /**
264
     * Sets the {@link Surface} to be used as the sink for the video portion of
265
     * the media. This is similar to {@link #setDisplay(SurfaceHolder)}, but
266
     * does not support {@link #setScreenOnWhilePlaying(boolean)}. Setting a
267
     * Surface will un-set any Surface or SurfaceHolder that was previously set.
268
     * A null surface will result in only the audio track being played.
269
     * 
270
     * If the Surface sends frames to a {@link SurfaceTexture}, the timestamps
271
     * returned from {@link SurfaceTexture#getTimestamp()} will have an
272
     * unspecified zero point. These timestamps cannot be directly compared
273
     * between different media sources, different instances of the same media
274
     * source, or multiple runs of the same program. The timestamp is normally
275
     * monotonically increasing and is unaffected by time-of-day adjustments,
276
     * but it is reset when the position is set.
277
     * 
278
     * @param surface
279
     *            The {@link Surface} to be used for the video portion of the
280
     *            media.
281
     */
282
    @Override
283
    public void setSurface(Surface surface) {
284
        if (mScreenOnWhilePlaying && surface != null) {
285
            DebugLog.w(TAG,
286
                    "setScreenOnWhilePlaying(true) is ineffective for Surface");
287
        }
288
        mSurfaceHolder = null;
289
        _setVideoSurface(surface);
290
        updateSurfaceScreenOn();
291
    }
292
293
    /**
294
     * Sets the data source as a content Uri.
295
     *
296
     * @param context the Context to use when resolving the Uri
297
     * @param uri the Content URI of the data you want to play
298
     * @throws IllegalStateException if it is called in an invalid state
299
     */
300
    @Override
301
    public void setDataSource(Context context, Uri uri)
302
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
303
        setDataSource(context, uri, null);
304
    }
305
306
    /**
307
     * Sets the data source as a content Uri.
308
     *
309
     * @param context the Context to use when resolving the Uri
310
     * @param uri the Content URI of the data you want to play
311
     * @param headers the headers to be sent together with the request for the data
312
     *                Note that the cross domain redirection is allowed by default, but that can be
313
     *                changed with key/value pairs through the headers parameter with
314
     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
315
     *                to disallow or allow cross domain redirection.
316
     * @throws IllegalStateException if it is called in an invalid state
317
     */
318
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
319
    @Override
320
    public void setDataSource(Context context, Uri uri, Map<String, String> headers)
321
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
322
        final String scheme = uri.getScheme();
323
        if (ContentResolver.SCHEME_FILE.equals(scheme)) {
324
            setDataSource(uri.getPath());
325
            return;
326
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
327
                && Settings.AUTHORITY.equals(uri.getAuthority())) {
328
            // Redirect ringtones to go directly to underlying provider
329
            uri = RingtoneManager.getActualDefaultRingtoneUri(context,
330
                    RingtoneManager.getDefaultType(uri));
331
            if (uri == null) {
332
                throw new FileNotFoundException("Failed to resolve default ringtone");
333
            }
334
        }
335
336
        AssetFileDescriptor fd = null;
337
        try {
338
            ContentResolver resolver = context.getContentResolver();
339
            fd = resolver.openAssetFileDescriptor(uri, "r");
340
            if (fd == null) {
341
                return;
342
            }
343
            // Note: using getDeclaredLength so that our behavior is the same
344
            // as previous versions when the content provider is returning
345
            // a full file.
346
            if (fd.getDeclaredLength() < 0) {
347
                setDataSource(fd.getFileDescriptor());
348
            } else {
349
                setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
350
            }
351
            return;
352
        } catch (SecurityException ignored) {
353
        } catch (IOException ignored) {
354
        } finally {
355
            if (fd != null) {
356
                fd.close();
357
            }
358
        }
359
360
        Log.d(TAG, "Couldn't open file on client side, trying server side");
361
362
        setDataSource(uri.toString(), headers);
363
    }
364
365
    /**
366
     * Sets the data source (file-path or http/rtsp URL) to use.
367
     * 
368
     * @param path
369
     *            the path of the file, or the http/rtsp URL of the stream you
370
     *            want to play
371
     * @throws IllegalStateException
372
     *             if it is called in an invalid state
373
     * 
374
     *             <p>
375
     *             When <code>path</code> refers to a local file, the file may
376
     *             actually be opened by a process other than the calling
377
     *             application. This implies that the pathname should be an
378
     *             absolute path (as any other process runs with unspecified
379
     *             current working directory), and that the pathname should
380
     *             reference a world-readable file.
381
     */
382
    @Override
383
    public void setDataSource(String path)
384
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
385
        mDataSource = path;
386
        _setDataSource(path, null, null);
387
    }
388
389
    /**
390
     * Sets the data source (file-path or http/rtsp URL) to use.
391
     *
392
     * @param path the path of the file, or the http/rtsp URL of the stream you want to play
393
     * @param headers the headers associated with the http request for the stream you want to play
394
     * @throws IllegalStateException if it is called in an invalid state
395
     */
396
    public void setDataSource(String path, Map<String, String> headers)
397
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException
398
    {
399
        if (headers != null && !headers.isEmpty()) {
400
            StringBuilder sb = new StringBuilder();
401
            for(Map.Entry<String, String> entry: headers.entrySet()) {
402
                sb.append(entry.getKey());
403
                sb.append(":");
404
                String value = entry.getValue();
405
                if (!TextUtils.isEmpty(value))
406
                    sb.append(entry.getValue());
407
                sb.append("\r\n");
408
                setOption(OPT_CATEGORY_FORMAT, "headers", sb.toString());
409
            }
410
        }
411
        setDataSource(path);
412
    }
413
414
    /**
415
     * Sets the data source (FileDescriptor) to use. It is the caller's responsibility
416
     * to close the file descriptor. It is safe to do so as soon as this call returns.
417
     *
418
     * @param fd the FileDescriptor for the file you want to play
419
     * @throws IllegalStateException if it is called in an invalid state
420
     */
421
    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
422
    @Override
423
    public void setDataSource(FileDescriptor fd)
424
            throws IOException, IllegalArgumentException, IllegalStateException {
425
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
426
            int native_fd = -1;
427
            try {
428
                Field f = fd.getClass().getDeclaredField("descriptor"); //NoSuchFieldException
429
                f.setAccessible(true);
430
                native_fd = f.getInt(fd); //IllegalAccessException
431
            } catch (NoSuchFieldException e) {
432
                throw new RuntimeException(e);
433
            } catch (IllegalAccessException e) {
434
                throw new RuntimeException(e);
435
            }
436
            _setDataSourceFd(native_fd);
437
        } else {
438
            ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(fd);
439
            try {
440
                _setDataSourceFd(pfd.getFd());
441
            } finally {
442
                pfd.close();
443
            }
444
        }
445
    }
446
447
    /**
448
     * Sets the data source (FileDescriptor) to use.  The FileDescriptor must be
449
     * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility
450
     * to close the file descriptor. It is safe to do so as soon as this call returns.
451
     *
452
     * @param fd the FileDescriptor for the file you want to play
453
     * @param offset the offset into the file where the data to be played starts, in bytes
454
     * @param length the length in bytes of the data to be played
455
     * @throws IllegalStateException if it is called in an invalid state
456
     */
457
    private void setDataSource(FileDescriptor fd, long offset, long length)
458
            throws IOException, IllegalArgumentException, IllegalStateException {
459
        // FIXME: handle offset, length
460
        setDataSource(fd);
461
    }
462
463
    public void setDataSource(IMediaDataSource mediaDataSource)
464
            throws IllegalArgumentException, SecurityException, IllegalStateException {
465
        _setDataSource(mediaDataSource);
466
    }
467
468
    private native void _setDataSource(String path, String[] keys, String[] values)
469
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
470
471
    private native void _setDataSourceFd(int fd)
472
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException;
473
474
    private native void _setDataSource(IMediaDataSource mediaDataSource)
475
            throws IllegalArgumentException, SecurityException, IllegalStateException;
476
477
    @Override
478
    public String getDataSource() {
479
        return mDataSource;
480
    }
481
482
    @Override
483
    public void prepareAsync() throws IllegalStateException {
484
        _prepareAsync();
485
    }
486
487
    public native void _prepareAsync() throws IllegalStateException;
488
489
    @Override
490
    public void start() throws IllegalStateException {
491
        stayAwake(true);
492
        _start();
493
    }
494
495
    private native void _start() throws IllegalStateException;
496
497
    @Override
498
    public void stop() throws IllegalStateException {
499
        stayAwake(false);
500
        _stop();
501
    }
502
503
    private native void _stop() throws IllegalStateException;
504
505
    @Override
506
    public void pause() throws IllegalStateException {
507
        stayAwake(false);
508
        _pause();
509
    }
510
511
    private native void _pause() throws IllegalStateException;
512
513
    @SuppressLint("Wakelock")
514
    @Override
515
    public void setWakeMode(Context context, int mode) {
516
        boolean washeld = false;
517
        if (mWakeLock != null) {
518
            if (mWakeLock.isHeld()) {
519
                washeld = true;
520
                mWakeLock.release();
521
            }
522
            mWakeLock = null;
523
        }
524
525
        PowerManager pm = (PowerManager) context
526
                .getSystemService(Context.POWER_SERVICE);
527
        mWakeLock = pm.newWakeLock(mode | PowerManager.ON_AFTER_RELEASE,
528
                IjkMediaPlayer.class.getName());
529
        mWakeLock.setReferenceCounted(false);
530
        if (washeld) {
531
            mWakeLock.acquire();
532
        }
533
    }
534
535
    @Override
536
    public void setScreenOnWhilePlaying(boolean screenOn) {
537
        if (mScreenOnWhilePlaying != screenOn) {
538
            if (screenOn && mSurfaceHolder == null) {
539
                DebugLog.w(TAG,
540
                        "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder");
541
            }
542
            mScreenOnWhilePlaying = screenOn;
543
            updateSurfaceScreenOn();
544
        }
545
    }
546
547
    @SuppressLint("Wakelock")
548
    private void stayAwake(boolean awake) {
549
        if (mWakeLock != null) {
550
            if (awake && !mWakeLock.isHeld()) {
551
                mWakeLock.acquire();
552
            } else if (!awake && mWakeLock.isHeld()) {
553
                mWakeLock.release();
554
            }
555
        }
556
        mStayAwake = awake;
557
        updateSurfaceScreenOn();
558
    }
559
560
    private void updateSurfaceScreenOn() {
561
        if (mSurfaceHolder != null) {
562
            mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake);
563
        }
564
    }
565
566
    @Override
567
    public IjkTrackInfo[] getTrackInfo() {
568
        Bundle bundle = getMediaMeta();
569
        if (bundle == null)
570
            return null;
571
572
        IjkMediaMeta mediaMeta = IjkMediaMeta.parse(bundle);
573
        if (mediaMeta == null || mediaMeta.mStreams == null)
574
            return null;
575
576
        ArrayList<IjkTrackInfo> trackInfos = new ArrayList<IjkTrackInfo>();
577
        for (IjkMediaMeta.IjkStreamMeta streamMeta: mediaMeta.mStreams) {
578
            IjkTrackInfo trackInfo = new IjkTrackInfo(streamMeta);
579
            if (streamMeta.mType.equalsIgnoreCase(IjkMediaMeta.IJKM_VAL_TYPE__VIDEO)) {
580
                trackInfo.setTrackType(ITrackInfo.MEDIA_TRACK_TYPE_VIDEO);
581
            } else if (streamMeta.mType.equalsIgnoreCase(IjkMediaMeta.IJKM_VAL_TYPE__AUDIO)) {
582
                trackInfo.setTrackType(ITrackInfo.MEDIA_TRACK_TYPE_AUDIO);
583
            }
584
            trackInfos.add(trackInfo);
585
        }
586
587
        return trackInfos.toArray(new IjkTrackInfo[trackInfos.size()]);
588
    }
589
590
    // TODO: @Override
591
    public int getSelectedTrack(int trackType) {
592
        switch (trackType) {
593
            case ITrackInfo.MEDIA_TRACK_TYPE_VIDEO:
594
                return (int)_getPropertyLong(FFP_PROP_INT64_SELECTED_VIDEO_STREAM, -1);
595
            case ITrackInfo.MEDIA_TRACK_TYPE_AUDIO:
596
                return (int)_getPropertyLong(FFP_PROP_INT64_SELECTED_AUDIO_STREAM, -1);
597
            default:
598
                return -1;
599
        }
600
    }
601
602
    // experimental, should set DEFAULT_MIN_FRAMES and MAX_MIN_FRAMES to 25
603
    // TODO: @Override
604
    public void selectTrack(int track) {
605
        _setStreamSelected(track, true);
606
    }
607
608
    // experimental, should set DEFAULT_MIN_FRAMES and MAX_MIN_FRAMES to 25
609
    // TODO: @Override
610
    public void deselectTrack(int track) {
611
        _setStreamSelected(track, false);
612
    }
613
614
    private native void _setStreamSelected(int stream, boolean select);
615
616
    @Override
617
    public int getVideoWidth() {
618
        return mVideoWidth;
619
    }
620
621
    @Override
622
    public int getVideoHeight() {
623
        return mVideoHeight;
624
    }
625
626
    @Override
627
    public int getVideoSarNum() {
628
        return mVideoSarNum;
629
    }
630
631
    @Override
632
    public int getVideoSarDen() {
633
        return mVideoSarDen;
634
    }
635
636
    @Override
637
    public native boolean isPlaying();
638
639
    @Override
640
    public native void seekTo(long msec) throws IllegalStateException;
641
642
    @Override
643
    public native long getCurrentPosition();
644
645
    @Override
646
    public native long getDuration();
647
648
    /**
649
     * Releases resources associated with this IjkMediaPlayer object. It is
650
     * considered good practice to call this method when you're done using the
651
     * IjkMediaPlayer. In particular, whenever an Activity of an application is
652
     * paused (its onPause() method is called), or stopped (its onStop() method
653
     * is called), this method should be invoked to release the IjkMediaPlayer
654
     * object, unless the application has a special need to keep the object
655
     * around. In addition to unnecessary resources (such as memory and
656
     * instances of codecs) being held, failure to call this method immediately
657
     * if a IjkMediaPlayer object is no longer needed may also lead to
658
     * continuous battery consumption for mobile devices, and playback failure
659
     * for other applications if no multiple instances of the same codec are
660
     * supported on a device. Even if multiple instances of the same codec are
661
     * supported, some performance degradation may be expected when unnecessary
662
     * multiple instances are used at the same time.
663
     */
664
    @Override
665
    public void release() {
666
        stayAwake(false);
667
        updateSurfaceScreenOn();
668
        resetListeners();
669
        _release();
670
    }
671
672
    private native void _release();
673
674
    @Override
675
    public void reset() {
676
        stayAwake(false);
677
        _reset();
678
        // make sure none of the listeners get called anymore
679
        mEventHandler.removeCallbacksAndMessages(null);
680
681
        mVideoWidth = 0;
682
        mVideoHeight = 0;
683
    }
684
685
    private native void _reset();
686
687
    /**
688
     * Sets the player to be looping or non-looping.
689
     *
690
     * @param looping whether to loop or not
691
     */
692
    @Override
693
    public void setLooping(boolean looping) {
694
        int loopCount = looping ? 0 : 1;
695
        setOption(OPT_CATEGORY_PLAYER, "loop", loopCount);
696
        _setLoopCount(loopCount);
697
    }
698
699
    private native void _setLoopCount(int loopCount);
700
701
    /**
702
     * Checks whether the MediaPlayer is looping or non-looping.
703
     *
704
     * @return true if the MediaPlayer is currently looping, false otherwise
705
     */
706
    @Override
707
    public boolean isLooping() {
708
        int loopCount = _getLoopCount();
709
        return loopCount != 1;
710
    }
711
712
    private native int _getLoopCount();
713
714
    @TargetApi(Build.VERSION_CODES.M)
715
    public void setSpeed(float speed) {
716
        _setPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, speed);
717
    }
718
719
    @TargetApi(Build.VERSION_CODES.M)
720
    public float getSpeed(float speed) {
721
        return _getPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, .0f);
722
    }
723
724
    public int getVideoDecoder() {
725
        return (int)_getPropertyLong(FFP_PROP_INT64_VIDEO_DECODER, FFP_PROPV_DECODER_UNKNOWN);
726
    }
727
728
    public float getVideoOutputFramesPerSecond() {
729
        return _getPropertyFloat(PROP_FLOAT_VIDEO_OUTPUT_FRAMES_PER_SECOND, 0.0f);
730
    }
731
732
    public float getVideoDecodeFramesPerSecond() {
733
        return _getPropertyFloat(PROP_FLOAT_VIDEO_DECODE_FRAMES_PER_SECOND, 0.0f);
734
    }
735
736
    public long getVideoCachedDuration() {
737
        return _getPropertyLong(FFP_PROP_INT64_VIDEO_CACHED_DURATION, 0);
738
    }
739
740
    public long getAudioCachedDuration() {
741
        return _getPropertyLong(FFP_PROP_INT64_AUDIO_CACHED_DURATION, 0);
742
    }
743
744
    public long getVideoCachedBytes() {
745
        return _getPropertyLong(FFP_PROP_INT64_VIDEO_CACHED_BYTES, 0);
746
    }
747
748
    public long getAudioCachedBytes() {
749
        return _getPropertyLong(FFP_PROP_INT64_AUDIO_CACHED_BYTES, 0);
750
    }
751
752
    public long getVideoCachedPackets() {
753
        return _getPropertyLong(FFP_PROP_INT64_VIDEO_CACHED_PACKETS, 0);
754
    }
755
756
    public long getAudioCachedPackets() {
757
        return _getPropertyLong(FFP_PROP_INT64_AUDIO_CACHED_PACKETS, 0);
758
    }
759
760
    public long getBitrate() {
761
        return _getPropertyLong(FFP_PROP_INT64_BIT_RATE, 0);
762
    }
763
764
    public long getTcpSpeed() {
765
        return _getPropertyLong(FFP_PROP_INT64_TCP_SPEED, 0);
766
    }
767
768
    public long getSeekLoadDuration() {
769
        return _getPropertyLong(FFP_PROP_INT64_LATEST_SEEK_LOAD_DURATION, 0);
770
    }
771
772
    private native float _getPropertyFloat(int property, float defaultValue);
773
    private native void  _setPropertyFloat(int property, float value);
774
    private native long  _getPropertyLong(int property, long defaultValue);
775
    private native void  _setPropertyLong(int property, long value);
776
777
    @Override
778
    public native void setVolume(float leftVolume, float rightVolume);
779
780
    @Override
781
    public native int getAudioSessionId();
782
783
    @Override
784
    public MediaInfo getMediaInfo() {
785
        MediaInfo mediaInfo = new MediaInfo();
786
        mediaInfo.mMediaPlayerName = "ijkplayer";
787
788
        String videoCodecInfo = _getVideoCodecInfo();
789
        if (!TextUtils.isEmpty(videoCodecInfo)) {
790
            String nodes[] = videoCodecInfo.split(",");
791
            if (nodes.length >= 2) {
792
                mediaInfo.mVideoDecoder = nodes[0];
793
                mediaInfo.mVideoDecoderImpl = nodes[1];
794
            } else if (nodes.length >= 1) {
795
                mediaInfo.mVideoDecoder = nodes[0];
796
                mediaInfo.mVideoDecoderImpl = "";
797
            }
798
        }
799
800
        String audioCodecInfo = _getAudioCodecInfo();
801
        if (!TextUtils.isEmpty(audioCodecInfo)) {
802
            String nodes[] = audioCodecInfo.split(",");
803
            if (nodes.length >= 2) {
804
                mediaInfo.mAudioDecoder = nodes[0];
805
                mediaInfo.mAudioDecoderImpl = nodes[1];
806
            } else if (nodes.length >= 1) {
807
                mediaInfo.mAudioDecoder = nodes[0];
808
                mediaInfo.mAudioDecoderImpl = "";
809
            }
810
        }
811
812
        try {
813
            mediaInfo.mMeta = IjkMediaMeta.parse(_getMediaMeta());
814
        } catch (Throwable e) {
815
            e.printStackTrace();
816
        }
817
        return mediaInfo;
818
    }
819
820
    @Override
821
    public void setLogEnabled(boolean enable) {
822
        // do nothing
823
    }
824
825
    @Override
826
    public boolean isPlayable() {
827
        return true;
828
    }
829
830
    private native String _getVideoCodecInfo();
831
    private native String _getAudioCodecInfo();
832
833
    public void setOption(int category, String name, String value)
834
    {
835
        _setOption(category, name, value);
836
    }
837
838
    public void setOption(int category, String name, long value)
839
    {
840
        _setOption(category, name, value);
841
    }
842
843
    private native void _setOption(int category, String name, String value);
844
    private native void _setOption(int category, String name, long value);
845
846
    public Bundle getMediaMeta() {
847
        return _getMediaMeta();
848
    }
849
    private native Bundle _getMediaMeta();
850
    public native Bundle _getMetaData();
851
852
    public static String getColorFormatName(int mediaCodecColorFormat) {
853
        return _getColorFormatName(mediaCodecColorFormat);
854
    }
855
856
    private static native String _getColorFormatName(int mediaCodecColorFormat);
857
858
    @Override
859
    public void setAudioStreamType(int streamtype) {
860
        // do nothing
861
    }
862
863
    @Override
864
    public void setKeepInBackground(boolean keepInBackground) {
865
        // do nothing
866
    }
867
868
    private static native void native_init();
869
870
    private native void native_setup(Object IjkMediaPlayer_this);
871
872
    private native void native_finalize();
873
874
    private native void native_message_loop(Object IjkMediaPlayer_this);
875
876
    protected void finalize() throws Throwable {
877
        super.finalize();
878
        native_finalize();
879
    }
880
881
    private static class EventHandler extends Handler {
882
        private final WeakReference<IjkMediaPlayer> mWeakPlayer;
883
884
        public EventHandler(IjkMediaPlayer mp, Looper looper) {
885
            super(looper);
886
            mWeakPlayer = new WeakReference<IjkMediaPlayer>(mp);
887
        }
888
889
        @Override
890
        public void handleMessage(Message msg) {
891
            IjkMediaPlayer player = mWeakPlayer.get();
892
            if (player == null || player.mNativeMediaPlayer == 0) {
893
                DebugLog.w(TAG,
894
                        "IjkMediaPlayer went away with unhandled events");
895
                return;
896
            }
897
898
            switch (msg.what) {
899
            case MEDIA_PREPARED:
900
                player.notifyOnPrepared();
901
                return;
902
903
            case MEDIA_PLAYBACK_COMPLETE:
904
                player.stayAwake(false);
905
                player.notifyOnCompletion();
906
                return;
907
908
            case MEDIA_BUFFERING_UPDATE:
909
                long bufferPosition = msg.arg1;
910
                if (bufferPosition < 0) {
911
                    bufferPosition = 0;
912
                }
913
914
                long percent = 0;
915
                long duration = player.getDuration();
916
                if (duration > 0) {
917
                    percent = bufferPosition * 100 / duration;
918
                }
919
                if (percent >= 100) {
920
                    percent = 100;
921
                }
922
923
                // DebugLog.efmt(TAG, "Buffer (%d%%) %d/%d",  percent, bufferPosition, duration);
924
                player.notifyOnBufferingUpdate((int)percent);
925
                return;
926
927
            case MEDIA_SEEK_COMPLETE:
928
                player.notifyOnSeekComplete();
929
                return;
930
931
            case MEDIA_SET_VIDEO_SIZE:
932
                player.mVideoWidth = msg.arg1;
933
                player.mVideoHeight = msg.arg2;
934
                player.notifyOnVideoSizeChanged(player.mVideoWidth, player.mVideoHeight,
935
                        player.mVideoSarNum, player.mVideoSarDen);
936
                return;
937
938
            case MEDIA_ERROR:
939
                DebugLog.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
940
                if (!player.notifyOnError(msg.arg1, msg.arg2)) {
941
                    player.notifyOnCompletion();
942
                }
943
                player.stayAwake(false);
944
                return;
945
946
            case MEDIA_INFO:
947
                switch (msg.arg1) {
948
                    case MEDIA_INFO_VIDEO_RENDERING_START:
949
                        DebugLog.i(TAG, "Info: MEDIA_INFO_VIDEO_RENDERING_START\n");
950
                        break;
951
                }
952
                player.notifyOnInfo(msg.arg1, msg.arg2);
953
                // No real default action so far.
954
                return;
955
            case MEDIA_TIMED_TEXT:
956
                // do nothing
957
                break;
958
959
            case MEDIA_NOP: // interface test message - ignore
960
                break;
961
962
            case MEDIA_SET_VIDEO_SAR:
963
                player.mVideoSarNum = msg.arg1;
964
                player.mVideoSarDen = msg.arg2;
965
                player.notifyOnVideoSizeChanged(player.mVideoWidth, player.mVideoHeight,
966
                        player.mVideoSarNum, player.mVideoSarDen);
967
                break;
968
969
            default:
970
                DebugLog.e(TAG, "Unknown message type " + msg.what);
971
            }
972
        }
973
    }
974
975
    /*
976
     * Called from native code when an interesting event happens. This method
977
     * just uses the EventHandler system to post the event back to the main app
978
     * thread. We use a weak reference to the original IjkMediaPlayer object so
979
     * that the native code is safe from the object disappearing from underneath
980
     * it. (This is the cookie passed to native_setup().)
981
     */
982
    @CalledByNative
983
    private static void postEventFromNative(Object weakThiz, int what,
984
            int arg1, int arg2, Object obj) {
985
        if (weakThiz == null)
986
            return;
987
988
        @SuppressWarnings("rawtypes")
989
        IjkMediaPlayer mp = (IjkMediaPlayer) ((WeakReference) weakThiz).get();
990
        if (mp == null) {
991
            return;
992
        }
993
994
        if (what == MEDIA_INFO && arg1 == MEDIA_INFO_STARTED_AS_NEXT) {
995
            // this acquires the wakelock if needed, and sets the client side
996
            // state
997
            mp.start();
998
        }
999
        if (mp.mEventHandler != null) {
1000
            Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
1001
            mp.mEventHandler.sendMessage(m);
1002
        }
1003
    }
1004
1005
    /*
1006
     * ControlMessage
1007
     */
1008
1009
    private OnControlMessageListener mOnControlMessageListener;
1010
    public void setOnControlMessageListener(OnControlMessageListener listener) {
1011
        mOnControlMessageListener = listener;
1012
    }
1013
1014
    public interface OnControlMessageListener {
1015
        String onControlResolveSegmentUrl(int segment);
1016
    }
1017
1018
    /*
1019
     * NativeInvoke
1020
     */
1021
1022
    private OnNativeInvokeListener mOnNativeInvokeListener;
1023
    public void setOnNativeInvokeListener(OnNativeInvokeListener listener) {
1024
        mOnNativeInvokeListener = listener;
1025
    }
1026
1027
    public interface OnNativeInvokeListener {
1028
        int ON_CONCAT_RESOLVE_SEGMENT = 0x10000;
1029
        int ON_TCP_OPEN = 0x10001;
1030
        int ON_HTTP_OPEN = 0x10002;
1031
        // int ON_HTTP_RETRY = 0x10003;
1032
        int ON_LIVE_RETRY = 0x10004;
1033
1034
        String ARG_URL = "url";
1035
        String ARG_SEGMENT_INDEX = "segment_index";
1036
        String ARG_RETRY_COUNTER = "retry_counter";
1037
1038
        /*
1039
         * @return true if invoke is handled
1040
         * @throws Exception on any error
1041
         */
1042
        boolean onNativeInvoke(int what, Bundle args);
1043
    }
1044
1045
    @CalledByNative
1046
    private static boolean onNativeInvoke(Object weakThiz, int what, Bundle args) {
1047
        DebugLog.ifmt(TAG, "onNativeInvoke %d", what);
1048
        if (weakThiz == null || !(weakThiz instanceof WeakReference<?>))
1049
            throw new IllegalStateException("<null weakThiz>.onNativeInvoke()");
1050
1051
        @SuppressWarnings("unchecked")
1052
        WeakReference<IjkMediaPlayer> weakPlayer = (WeakReference<IjkMediaPlayer>) weakThiz;
1053
        IjkMediaPlayer player = weakPlayer.get();
1054
        if (player == null)
1055
            throw new IllegalStateException("<null weakPlayer>.onNativeInvoke()");
1056
1057
        OnNativeInvokeListener listener = player.mOnNativeInvokeListener;
1058
        if (listener != null && listener.onNativeInvoke(what, args))
1059
            return true;
1060
1061
        switch (what) {
1062
            case OnNativeInvokeListener.ON_CONCAT_RESOLVE_SEGMENT: {
1063
                OnControlMessageListener onControlMessageListener = player.mOnControlMessageListener;
1064
                if (onControlMessageListener == null)
1065
                    return false;
1066
1067
                int segmentIndex = args.getInt(OnNativeInvokeListener.ARG_SEGMENT_INDEX, -1);
1068
                if (segmentIndex < 0)
1069
                    throw new InvalidParameterException("onNativeInvoke(invalid segment index)");
1070
1071
                String newUrl = onControlMessageListener.onControlResolveSegmentUrl(segmentIndex);
1072
                if (newUrl == null)
1073
                    throw new RuntimeException(new IOException("onNativeInvoke() = <NULL newUrl>"));
1074
1075
                args.putString(OnNativeInvokeListener.ARG_URL, newUrl);
1076
                return true;
1077
            }
1078
            default:
1079
                return false;
1080
        }
1081
    }
1082
1083
    /*
1084
     * MediaCodec select
1085
     */
1086
1087
    public interface OnMediaCodecSelectListener {
1088
        String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level);
1089
    }
1090
    private OnMediaCodecSelectListener mOnMediaCodecSelectListener;
1091
    public void setOnMediaCodecSelectListener(OnMediaCodecSelectListener listener) {
1092
        mOnMediaCodecSelectListener = listener;
1093
    }
1094
1095
    public void resetListeners() {
1096
        super.resetListeners();
1097
        mOnMediaCodecSelectListener = null;
1098
    }
1099
1100
    @CalledByNative
1101
    private static String onSelectCodec(Object weakThiz, String mimeType, int profile, int level) {
1102
        if (weakThiz == null || !(weakThiz instanceof WeakReference<?>))
1103
            return null;
1104
1105
        @SuppressWarnings("unchecked")
1106
        WeakReference<IjkMediaPlayer> weakPlayer = (WeakReference<IjkMediaPlayer>) weakThiz;
1107
        IjkMediaPlayer player = weakPlayer.get();
1108
        if (player == null)
1109
            return null;
1110
1111
        OnMediaCodecSelectListener listener = player.mOnMediaCodecSelectListener;
1112
        if (listener == null)
1113
            listener = DefaultMediaCodecSelector.sInstance;
1114
1115
        return listener.onMediaCodecSelect(player, mimeType, profile, level);
1116
    }
1117
1118
    public static class DefaultMediaCodecSelector implements OnMediaCodecSelectListener {
1119
        public static final DefaultMediaCodecSelector sInstance = new DefaultMediaCodecSelector();
1120
1121
        @SuppressWarnings("deprecation")
1122
        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
1123
        public String onMediaCodecSelect(IMediaPlayer mp, String mimeType, int profile, int level) {
1124
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
1125
                return null;
1126
1127
            if (TextUtils.isEmpty(mimeType))
1128
                return null;
1129
1130
            Log.i(TAG, String.format(Locale.US, "onSelectCodec: mime=%s, profile=%d, level=%d", mimeType, profile, level));
1131
            ArrayList<IjkMediaCodecInfo> candidateCodecList = new ArrayList<IjkMediaCodecInfo>();
1132
            int numCodecs = MediaCodecList.getCodecCount();
1133
            for (int i = 0; i < numCodecs; i++) {
1134
                MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
1135
                Log.d(TAG, String.format(Locale.US, "  found codec: %s", codecInfo.getName()));
1136
                if (codecInfo.isEncoder())
1137
                    continue;
1138
1139
                String[] types = codecInfo.getSupportedTypes();
1140
                if (types == null)
1141
                    continue;
1142
1143
                for(String type: types) {
1144
                    if (TextUtils.isEmpty(type))
1145
                        continue;
1146
1147
                    Log.d(TAG, String.format(Locale.US, "    mime: %s", type));
1148
                    if (!type.equalsIgnoreCase(mimeType))
1149
                        continue;
1150
1151
                    IjkMediaCodecInfo candidate = IjkMediaCodecInfo.setupCandidate(codecInfo, mimeType);
1152
                    if (candidate == null)
1153
                        continue;
1154
1155
                    candidateCodecList.add(candidate);
1156
                    Log.i(TAG, String.format(Locale.US, "candidate codec: %s rank=%d", codecInfo.getName(), candidate.mRank));
1157
                    candidate.dumpProfileLevels(mimeType);
1158
                }
1159
            }
1160
1161
            if (candidateCodecList.isEmpty()) {
1162
                return null;
1163
            }
1164
1165
            IjkMediaCodecInfo bestCodec = candidateCodecList.get(0);
1166
1167
            for (IjkMediaCodecInfo codec : candidateCodecList) {
1168
                if (codec.mRank > bestCodec.mRank) {
1169
                    bestCodec = codec;
1170
                }
1171
            }
1172
1173
            if (bestCodec.mRank < IjkMediaCodecInfo.RANK_LAST_CHANCE) {
1174
                Log.w(TAG, String.format(Locale.US, "unaccetable codec: %s", bestCodec.mCodecInfo.getName()));
1175
                return null;
1176
            }
1177
1178
            Log.i(TAG, String.format(Locale.US, "selected codec: %s rank=%d", bestCodec.mCodecInfo.getName(), bestCodec.mRank));
1179
            return bestCodec.mCodecInfo.getName();
1180
        }
1181
    }
1182
1183
    public static native void native_profileBegin(String libName);
1184
    public static native void native_profileEnd();
1185
    public static native void native_setLogLevel(int level);
1186
1187
    private native void _setAudioDataCallback();
1188
    private native void _delAudioDataCallback();
1189
1190
    private OnAudioDataCallback mAudioDataCallback = null;
1191
1192
    public void setOnAudioDataCallback(OnAudioDataCallback callback) {
1193
        if (callback != null) {
1194
            this.mAudioDataCallback = callback;
1195
            _setAudioDataCallback();
1196
        } else {
1197
            this.mAudioDataCallback = null;
1198
            _delAudioDataCallback();
1199
        }
1200
    }
1201
1202
    public interface OnAudioDataCallback {
1203
        void onAudioData(byte[] audio_data, int len);
1204
    }
1205
1206
    // audio data callback
1207
    public void audioCallback(byte[] audio_data, int data_size) {
1208
        if (mAudioDataCallback != null) {
1209
            mAudioDataCallback.onAudioData(audio_data, data_size);
1210
        }
1211
    }
1212
}

+ 29 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaInfo.java

@ -0,0 +1,29 @@
1
/*
2
 * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
public class MediaInfo {
20
    public String mMediaPlayerName;
21
22
    public String mVideoDecoder;
23
    public String mVideoDecoderImpl;
24
25
    public String mAudioDecoder;
26
    public String mAudioDecoderImpl;
27
28
    public IjkMediaMeta mMeta;
29
}

+ 323 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/MediaPlayerProxy.java

@ -0,0 +1,323 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
import android.annotation.TargetApi;
20
import android.content.Context;
21
import android.net.Uri;
22
import android.os.Build;
23
import android.view.Surface;
24
import android.view.SurfaceHolder;
25
26
import java.io.FileDescriptor;
27
import java.io.IOException;
28
import java.util.Map;
29
30
import tv.danmaku.ijk.media.player.misc.IMediaDataSource;
31
import tv.danmaku.ijk.media.player.misc.ITrackInfo;
32
33
public class MediaPlayerProxy implements IMediaPlayer {
34
    protected final IMediaPlayer mBackEndMediaPlayer;
35
36
    public MediaPlayerProxy(IMediaPlayer backEndMediaPlayer) {
37
        mBackEndMediaPlayer = backEndMediaPlayer;
38
    }
39
40
    public IMediaPlayer getInternalMediaPlayer() {
41
        return mBackEndMediaPlayer;
42
    }
43
44
    @Override
45
    public void setDisplay(SurfaceHolder sh) {
46
        mBackEndMediaPlayer.setDisplay(sh);
47
    }
48
49
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
50
    @Override
51
    public void setSurface(Surface surface) {
52
        mBackEndMediaPlayer.setSurface(surface);
53
    }
54
55
    @Override
56
    public void setDataSource(Context context, Uri uri)
57
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
58
        mBackEndMediaPlayer.setDataSource(context, uri);
59
    }
60
61
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
62
    @Override
63
    public void setDataSource(Context context, Uri uri, Map<String, String> headers)
64
            throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
65
        mBackEndMediaPlayer.setDataSource(context, uri, headers);
66
    }
67
68
    @Override
69
    public void setDataSource(FileDescriptor fd)
70
            throws IOException, IllegalArgumentException, IllegalStateException {
71
        mBackEndMediaPlayer.setDataSource(fd);
72
    }
73
74
    @Override
75
    public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
76
        mBackEndMediaPlayer.setDataSource(path);
77
    }
78
79
    @Override
80
    public void setDataSource(IMediaDataSource mediaDataSource)  {
81
        mBackEndMediaPlayer.setDataSource(mediaDataSource);
82
    }
83
84
    @Override
85
    public String getDataSource() {
86
        return mBackEndMediaPlayer.getDataSource();
87
    }
88
89
    @Override
90
    public void prepareAsync() throws IllegalStateException {
91
        mBackEndMediaPlayer.prepareAsync();
92
    }
93
94
    @Override
95
    public void start() throws IllegalStateException {
96
        mBackEndMediaPlayer.start();
97
    }
98
99
    @Override
100
    public void stop() throws IllegalStateException {
101
        mBackEndMediaPlayer.stop();
102
    }
103
104
    @Override
105
    public void pause() throws IllegalStateException {
106
        mBackEndMediaPlayer.pause();
107
    }
108
109
    @Override
110
    public void setScreenOnWhilePlaying(boolean screenOn) {
111
        mBackEndMediaPlayer.setScreenOnWhilePlaying(screenOn);
112
    }
113
114
    @Override
115
    public int getVideoWidth() {
116
        return mBackEndMediaPlayer.getVideoWidth();
117
    }
118
119
    @Override
120
    public int getVideoHeight() {
121
        return mBackEndMediaPlayer.getVideoHeight();
122
    }
123
124
    @Override
125
    public boolean isPlaying() {
126
        return mBackEndMediaPlayer.isPlaying();
127
    }
128
129
    @Override
130
    public void seekTo(long msec) throws IllegalStateException {
131
        mBackEndMediaPlayer.seekTo(msec);
132
    }
133
134
    @Override
135
    public long getCurrentPosition() {
136
        return mBackEndMediaPlayer.getCurrentPosition();
137
    }
138
139
    @Override
140
    public long getDuration() {
141
        return mBackEndMediaPlayer.getDuration();
142
    }
143
144
    @Override
145
    public void release() {
146
        mBackEndMediaPlayer.release();
147
    }
148
149
    @Override
150
    public void reset() {
151
        mBackEndMediaPlayer.reset();
152
    }
153
154
    @Override
155
    public void setVolume(float leftVolume, float rightVolume) {
156
        mBackEndMediaPlayer.setVolume(leftVolume, rightVolume);
157
    }
158
159
    @Override
160
    public int getAudioSessionId() {
161
        return mBackEndMediaPlayer.getAudioSessionId();
162
    }
163
164
    @Override
165
    public MediaInfo getMediaInfo() {
166
        return mBackEndMediaPlayer.getMediaInfo();
167
    }
168
169
    @Override
170
    public void setLogEnabled(boolean enable) {
171
172
    }
173
174
    @Override
175
    public boolean isPlayable() {
176
        return false;
177
    }
178
179
    @Override
180
    public void setOnPreparedListener(OnPreparedListener listener) {
181
        if (listener != null) {
182
            final OnPreparedListener finalListener = listener;
183
            mBackEndMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
184
                @Override
185
                public void onPrepared(IMediaPlayer mp) {
186
                    finalListener.onPrepared(MediaPlayerProxy.this);
187
                }
188
            });
189
        } else {
190
            mBackEndMediaPlayer.setOnPreparedListener(null);
191
        }
192
    }
193
194
    @Override
195
    public void setOnCompletionListener(OnCompletionListener listener) {
196
        if (listener != null) {
197
            final OnCompletionListener finalListener = listener;
198
            mBackEndMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
199
                @Override
200
                public void onCompletion(IMediaPlayer mp) {
201
                    finalListener.onCompletion(MediaPlayerProxy.this);
202
                }
203
            });
204
        } else {
205
            mBackEndMediaPlayer.setOnCompletionListener(null);
206
        }
207
    }
208
209
    @Override
210
    public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) {
211
        if (listener != null) {
212
            final OnBufferingUpdateListener finalListener = listener;
213
            mBackEndMediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
214
                @Override
215
                public void onBufferingUpdate(IMediaPlayer mp, int percent) {
216
                    finalListener.onBufferingUpdate(MediaPlayerProxy.this, percent);
217
                }
218
            });
219
        } else {
220
            mBackEndMediaPlayer.setOnBufferingUpdateListener(null);
221
        }
222
    }
223
224
    @Override
225
    public void setOnSeekCompleteListener(OnSeekCompleteListener listener) {
226
        if (listener != null) {
227
            final OnSeekCompleteListener finalListener = listener;
228
            mBackEndMediaPlayer.setOnSeekCompleteListener(new OnSeekCompleteListener() {
229
                @Override
230
                public void onSeekComplete(IMediaPlayer mp) {
231
                    finalListener.onSeekComplete(MediaPlayerProxy.this);
232
                }
233
            });
234
        } else {
235
            mBackEndMediaPlayer.setOnSeekCompleteListener(null);
236
        }
237
    }
238
239
    @Override
240
    public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) {
241
        if (listener != null) {
242
            final OnVideoSizeChangedListener finalListener = listener;
243
            mBackEndMediaPlayer.setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
244
                @Override
245
                public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) {
246
                    finalListener.onVideoSizeChanged(MediaPlayerProxy.this, width, height, sar_num, sar_den);
247
                }
248
            });
249
        } else {
250
            mBackEndMediaPlayer.setOnVideoSizeChangedListener(null);
251
        }
252
    }
253
254
    @Override
255
    public void setOnErrorListener(OnErrorListener listener) {
256
        if (listener != null) {
257
            final OnErrorListener finalListener = listener;
258
            mBackEndMediaPlayer.setOnErrorListener(new OnErrorListener() {
259
                @Override
260
                public boolean onError(IMediaPlayer mp, int what, int extra) {
261
                    return finalListener.onError(MediaPlayerProxy.this, what, extra);
262
                }
263
            });
264
        } else {
265
            mBackEndMediaPlayer.setOnErrorListener(null);
266
        }
267
    }
268
269
    @Override
270
    public void setOnInfoListener(OnInfoListener listener) {
271
        if (listener != null) {
272
            final OnInfoListener finalListener = listener;
273
            mBackEndMediaPlayer.setOnInfoListener(new OnInfoListener() {
274
                @Override
275
                public boolean onInfo(IMediaPlayer mp, int what, int extra) {
276
                    return finalListener.onInfo(MediaPlayerProxy.this, what, extra);
277
                }
278
            });
279
        } else {
280
            mBackEndMediaPlayer.setOnInfoListener(null);
281
        }
282
    }
283
284
    @Override
285
    public void setAudioStreamType(int streamtype) {
286
        mBackEndMediaPlayer.setAudioStreamType(streamtype);
287
    }
288
289
    @Override
290
    public void setKeepInBackground(boolean keepInBackground) {
291
        mBackEndMediaPlayer.setKeepInBackground(keepInBackground);
292
    }
293
294
    @Override
295
    public int getVideoSarNum() {
296
        return mBackEndMediaPlayer.getVideoSarNum();
297
    }
298
299
    @Override
300
    public int getVideoSarDen() {
301
        return mBackEndMediaPlayer.getVideoSarDen();
302
    }
303
304
    @Override
305
    public void setWakeMode(Context context, int mode) {
306
        mBackEndMediaPlayer.setWakeMode(context, mode);
307
    }
308
309
    @Override
310
    public ITrackInfo[] getTrackInfo() {
311
        return mBackEndMediaPlayer.getTrackInfo();
312
    }
313
314
    @Override
315
    public void setLooping(boolean looping) {
316
        mBackEndMediaPlayer.setLooping(looping);
317
    }
318
319
    @Override
320
    public boolean isLooping() {
321
        return mBackEndMediaPlayer.isLooping();
322
    }
323
}

+ 99 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/TextureMediaPlayer.java

@ -0,0 +1,99 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player;
18
19
import android.annotation.TargetApi;
20
import android.graphics.SurfaceTexture;
21
import android.os.Build;
22
import android.view.Surface;
23
import android.view.SurfaceHolder;
24
25
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
26
public class TextureMediaPlayer extends MediaPlayerProxy implements IMediaPlayer, ISurfaceTextureHolder {
27
    private SurfaceTexture mSurfaceTexture;
28
    private ISurfaceTextureHost mSurfaceTextureHost;
29
30
    public TextureMediaPlayer(IMediaPlayer backEndMediaPlayer) {
31
        super(backEndMediaPlayer);
32
    }
33
34
    public void releaseSurfaceTexture() {
35
        if (mSurfaceTexture != null) {
36
            if (mSurfaceTextureHost != null) {
37
                mSurfaceTextureHost.releaseSurfaceTexture(mSurfaceTexture);
38
            } else {
39
                mSurfaceTexture.release();
40
            }
41
            mSurfaceTexture = null;
42
        }
43
    }
44
45
    //--------------------
46
    // IMediaPlayer
47
    //--------------------
48
    @Override
49
    public void reset() {
50
        super.reset();
51
        releaseSurfaceTexture();
52
    }
53
54
    @Override
55
    public void release() {
56
        super.release();
57
        releaseSurfaceTexture();
58
    }
59
60
    @Override
61
    public void setDisplay(SurfaceHolder sh) {
62
        if (mSurfaceTexture == null)
63
            super.setDisplay(sh);
64
    }
65
66
    @Override
67
    public void setSurface(Surface surface) {
68
        if (mSurfaceTexture == null)
69
            super.setSurface(surface);
70
    }
71
72
    //--------------------
73
    // ISurfaceTextureHolder
74
    //--------------------
75
76
    @Override
77
    public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
78
        if (mSurfaceTexture == surfaceTexture)
79
            return;
80
81
        releaseSurfaceTexture();
82
        mSurfaceTexture = surfaceTexture;
83
        if (surfaceTexture == null) {
84
            super.setSurface(null);
85
        } else {
86
            super.setSurface(new Surface(surfaceTexture));
87
        }
88
    }
89
90
    @Override
91
    public SurfaceTexture getSurfaceTexture() {
92
        return mSurfaceTexture;
93
    }
94
95
    @Override
96
    public void setSurfaceTextureHost(ISurfaceTextureHost surfaceTextureHost) {
97
        mSurfaceTextureHost = surfaceTextureHost;
98
    }
99
}

+ 31 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/annotations/AccessedByNative.java

@ -0,0 +1,31 @@
1
/*
2
 * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.annotations;
18
19
import java.lang.annotation.ElementType;
20
import java.lang.annotation.Retention;
21
import java.lang.annotation.RetentionPolicy;
22
import java.lang.annotation.Target;
23
24
/**
25
 * is used by the JNI generator to create the necessary JNI
26
 * bindings and expose this method to native code.
27
 */
28
@Target(ElementType.FIELD)
29
@Retention(RetentionPolicy.CLASS)
30
public @interface AccessedByNative {
31
}

+ 35 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/annotations/CalledByNative.java

@ -0,0 +1,35 @@
1
/*
2
 * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.annotations;
18
19
import java.lang.annotation.ElementType;
20
import java.lang.annotation.Retention;
21
import java.lang.annotation.RetentionPolicy;
22
import java.lang.annotation.Target;
23
24
/**
25
 * is used by the JNI generator to create the necessary JNI
26
 * bindings and expose this method to native code.
27
 */
28
@Target(ElementType.METHOD)
29
@Retention(RetentionPolicy.CLASS)
30
public @interface CalledByNative {
31
    /*
32
     * If present, tells which inner class the method belongs to.
33
     */
34
    String value() default "";
35
}

+ 21 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/exceptions/IjkMediaException.java

@ -0,0 +1,21 @@
1
/*
2
 * Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.exceptions;
18
19
public class IjkMediaException extends Exception {
20
    private static final long serialVersionUID = 7234796519009099506L;
21
}

+ 5 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/ffmpeg/FFmpegApi.java

@ -0,0 +1,5 @@
1
package tv.danmaku.ijk.media.player.ffmpeg;
2
3
public class FFmpegApi {
4
    public static native String av_base64_encode(byte in[]);
5
}

+ 62 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidMediaFormat.java

@ -0,0 +1,62 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.misc;
18
19
import android.annotation.TargetApi;
20
import android.media.MediaFormat;
21
import android.os.Build;
22
23
public class AndroidMediaFormat implements IMediaFormat {
24
    private final MediaFormat mMediaFormat;
25
26
    public AndroidMediaFormat(MediaFormat mediaFormat) {
27
        mMediaFormat = mediaFormat;
28
    }
29
30
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
31
    @Override
32
    public int getInteger(String name) {
33
        if (mMediaFormat == null)
34
            return 0;
35
36
        return mMediaFormat.getInteger(name);
37
    }
38
39
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
40
    @Override
41
    public String getString(String name) {
42
        if (mMediaFormat == null)
43
            return null;
44
45
        return mMediaFormat.getString(name);
46
    }
47
48
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
49
    @Override
50
    public String toString() {
51
        StringBuilder out = new StringBuilder(128);
52
        out.append(getClass().getName());
53
        out.append('{');
54
        if (mMediaFormat != null) {
55
            out.append(mMediaFormat.toString());
56
        } else {
57
            out.append("null");
58
        }
59
        out.append('}');
60
        return out.toString();
61
    }
62
}

+ 108 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/AndroidTrackInfo.java

@ -0,0 +1,108 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.misc;
18
19
import android.annotation.TargetApi;
20
import android.media.MediaFormat;
21
import android.media.MediaPlayer;
22
import android.os.Build;
23
24
public class AndroidTrackInfo implements ITrackInfo {
25
    private final MediaPlayer.TrackInfo mTrackInfo;
26
27
    public static AndroidTrackInfo[] fromMediaPlayer(MediaPlayer mp) {
28
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
29
            return fromTrackInfo(mp.getTrackInfo());
30
31
        return null;
32
    }
33
34
    private static AndroidTrackInfo[] fromTrackInfo(MediaPlayer.TrackInfo[] trackInfos) {
35
        if (trackInfos == null)
36
            return null;
37
38
        AndroidTrackInfo androidTrackInfo[] = new AndroidTrackInfo[trackInfos.length];
39
        for (int i = 0; i < trackInfos.length; ++i) {
40
            androidTrackInfo[i] = new AndroidTrackInfo(trackInfos[i]);
41
        }
42
43
        return androidTrackInfo;
44
    }
45
46
    private AndroidTrackInfo(MediaPlayer.TrackInfo trackInfo) {
47
        mTrackInfo = trackInfo;
48
    }
49
50
    @TargetApi(Build.VERSION_CODES.KITKAT)
51
    @Override
52
    public IMediaFormat getFormat() {
53
        if (mTrackInfo == null)
54
            return null;
55
56
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
57
            return null;
58
59
        MediaFormat mediaFormat = mTrackInfo.getFormat();
60
        if (mediaFormat == null)
61
            return null;
62
63
        return new AndroidMediaFormat(mediaFormat);
64
    }
65
66
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
67
    @Override
68
    public String getLanguage() {
69
        if (mTrackInfo == null)
70
            return "und";
71
72
        return mTrackInfo.getLanguage();
73
    }
74
75
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
76
    @Override
77
    public int getTrackType() {
78
        if (mTrackInfo == null)
79
            return MEDIA_TRACK_TYPE_UNKNOWN;
80
81
        return mTrackInfo.getTrackType();
82
    }
83
84
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
85
    @Override
86
    public String toString() {
87
        StringBuilder out = new StringBuilder(128);
88
        out.append(getClass().getSimpleName());
89
        out.append('{');
90
        if (mTrackInfo != null) {
91
            out.append(mTrackInfo.toString());
92
        } else {
93
            out.append("null");
94
        }
95
        out.append('}');
96
        return out.toString();
97
    }
98
99
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
100
    @Override
101
    public String getInfoInline() {
102
        if (mTrackInfo != null) {
103
            return mTrackInfo.toString();
104
        } else {
105
            return "null";
106
        }
107
    }
108
}

+ 28 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaDataSource.java

@ -0,0 +1,28 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.misc;
18
19
import java.io.IOException;
20
21
@SuppressWarnings("RedundantThrows")
22
public interface IMediaDataSource {
23
    int	 readAt(long position, byte[] buffer, int offset, int size) throws IOException;
24
25
    long getSize() throws IOException;
26
27
    void close() throws IOException;
28
}

+ 30 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IMediaFormat.java

@ -0,0 +1,30 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.misc;
18
19
public interface IMediaFormat {
20
    // Common keys
21
    String KEY_MIME = "mime";
22
23
    // Video Keys
24
    String KEY_WIDTH = "width";
25
    String KEY_HEIGHT = "height";
26
27
    String getString(String name);
28
29
    int getInteger(String name);
30
}

+ 34 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/ITrackInfo.java

@ -0,0 +1,34 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.misc;
18
19
public interface ITrackInfo {
20
    int MEDIA_TRACK_TYPE_AUDIO = 2;
21
    int MEDIA_TRACK_TYPE_METADATA = 5;
22
    int MEDIA_TRACK_TYPE_SUBTITLE = 4;
23
    int MEDIA_TRACK_TYPE_TIMEDTEXT = 3;
24
    int MEDIA_TRACK_TYPE_UNKNOWN = 0;
25
    int MEDIA_TRACK_TYPE_VIDEO = 1;
26
27
    IMediaFormat getFormat();
28
29
    String getLanguage();
30
31
    int getTrackType();
32
33
    String getInfoInline();
34
}

+ 209 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IjkMediaFormat.java

@ -0,0 +1,209 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.misc;
18
19
import android.annotation.TargetApi;
20
import android.os.Build;
21
import android.text.TextUtils;
22
23
import java.util.HashMap;
24
import java.util.Locale;
25
import java.util.Map;
26
27
import tv.danmaku.ijk.media.player.IjkMediaMeta;
28
29
public class IjkMediaFormat implements IMediaFormat {
30
    // Common
31
    public static final String KEY_IJK_CODEC_LONG_NAME_UI = "ijk-codec-long-name-ui";
32
    public static final String KEY_IJK_BIT_RATE_UI = "ijk-bit-rate-ui";
33
34
    // Video
35
    public static final String KEY_IJK_CODEC_PROFILE_LEVEL_UI = "ijk-profile-level-ui";
36
    public static final String KEY_IJK_CODEC_PIXEL_FORMAT_UI = "ijk-pixel-format-ui";
37
    public static final String KEY_IJK_RESOLUTION_UI = "ijk-resolution-ui";
38
    public static final String KEY_IJK_FRAME_RATE_UI = "ijk-frame-rate-ui";
39
40
    // Audio
41
    public static final String KEY_IJK_SAMPLE_RATE_UI = "ijk-sample-rate-ui";
42
    public static final String KEY_IJK_CHANNEL_UI = "ijk-channel-ui";
43
44
    // Codec
45
    public static final String CODEC_NAME_H264 = "h264";
46
47
    public final IjkMediaMeta.IjkStreamMeta mMediaFormat;
48
49
    public IjkMediaFormat(IjkMediaMeta.IjkStreamMeta streamMeta) {
50
        mMediaFormat = streamMeta;
51
    }
52
53
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
54
    @Override
55
    public int getInteger(String name) {
56
        if (mMediaFormat == null)
57
            return 0;
58
59
        return mMediaFormat.getInt(name);
60
    }
61
62
    @Override
63
    public String getString(String name) {
64
        if (mMediaFormat == null)
65
            return null;
66
67
        if (sFormatterMap.containsKey(name)) {
68
            Formatter formatter = sFormatterMap.get(name);
69
            return formatter.format(this);
70
        }
71
72
        return mMediaFormat.getString(name);
73
    }
74
75
    //-------------------------
76
    // Formatter
77
    //-------------------------
78
79
    private static abstract class Formatter {
80
        public String format(IjkMediaFormat mediaFormat) {
81
            String value = doFormat(mediaFormat);
82
            if (TextUtils.isEmpty(value))
83
                return getDefaultString();
84
            return value;
85
        }
86
87
        protected abstract String doFormat(IjkMediaFormat mediaFormat);
88
89
        @SuppressWarnings("SameReturnValue")
90
        protected String getDefaultString() {
91
            return "N/A";
92
        }
93
    }
94
95
    private static final Map<String, Formatter> sFormatterMap = new HashMap<String, Formatter>();
96
97
    {
98
        sFormatterMap.put(KEY_IJK_CODEC_LONG_NAME_UI, new Formatter() {
99
            @Override
100
            public String doFormat(IjkMediaFormat mediaFormat) {
101
                return mMediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_LONG_NAME);
102
            }
103
        });
104
        sFormatterMap.put(KEY_IJK_BIT_RATE_UI, new Formatter() {
105
            @Override
106
            protected String doFormat(IjkMediaFormat mediaFormat) {
107
                int bitRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_BITRATE);
108
                if (bitRate <= 0) {
109
                    return null;
110
                } else if (bitRate < 1000) {
111
                    return String.format(Locale.US, "%d bit/s", bitRate);
112
                } else {
113
                    return String.format(Locale.US, "%d kb/s", bitRate / 1000);
114
                }
115
            }
116
        });
117
        sFormatterMap.put(KEY_IJK_CODEC_PROFILE_LEVEL_UI, new Formatter() {
118
            @Override
119
            protected String doFormat(IjkMediaFormat mediaFormat) {
120
                String profile = mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_PROFILE);
121
                if (TextUtils.isEmpty(profile))
122
                    return null;
123
124
                StringBuilder sb = new StringBuilder();
125
                sb.append(profile);
126
127
                String codecName = mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_NAME);
128
                if (!TextUtils.isEmpty(codecName) && codecName.equalsIgnoreCase(CODEC_NAME_H264)) {
129
                    int level = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CODEC_LEVEL);
130
                    if (level < 10)
131
                        return sb.toString();
132
133
                    sb.append(" Profile Level ");
134
                    sb.append((level / 10) % 10);
135
                    if ((level % 10) != 0) {
136
                        sb.append(".");
137
                        sb.append(level % 10);
138
                    }
139
                }
140
141
                return sb.toString();
142
            }
143
        });
144
        sFormatterMap.put(KEY_IJK_CODEC_PIXEL_FORMAT_UI, new Formatter() {
145
            @Override
146
            protected String doFormat(IjkMediaFormat mediaFormat) {
147
                return mediaFormat.getString(IjkMediaMeta.IJKM_KEY_CODEC_PIXEL_FORMAT);
148
            }
149
        });
150
        sFormatterMap.put(KEY_IJK_RESOLUTION_UI, new Formatter() {
151
            @Override
152
            protected String doFormat(IjkMediaFormat mediaFormat) {
153
                int width = mediaFormat.getInteger(KEY_WIDTH);
154
                int height = mediaFormat.getInteger(KEY_HEIGHT);
155
                int sarNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_NUM);
156
                int sarDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAR_DEN);
157
158
                if (width <= 0 || height <= 0) {
159
                    return null;
160
                } else if (sarNum <= 0 || sarDen <= 0) {
161
                    return String.format(Locale.US, "%d x %d", width, height);
162
                } else {
163
                    return String.format(Locale.US, "%d x %d [SAR %d:%d]", width,
164
                            height, sarNum, sarDen);
165
                }
166
            }
167
        });
168
        sFormatterMap.put(KEY_IJK_FRAME_RATE_UI, new Formatter() {
169
            @Override
170
            protected String doFormat(IjkMediaFormat mediaFormat) {
171
                int fpsNum = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_NUM);
172
                int fpsDen = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_FPS_DEN);
173
                if (fpsNum <= 0 || fpsDen <= 0) {
174
                    return null;
175
                } else {
176
                    return String.valueOf(((float) (fpsNum)) / fpsDen);
177
                }
178
            }
179
        });
180
        sFormatterMap.put(KEY_IJK_SAMPLE_RATE_UI, new Formatter() {
181
            @Override
182
            protected String doFormat(IjkMediaFormat mediaFormat) {
183
                int sampleRate = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_SAMPLE_RATE);
184
                if (sampleRate <= 0) {
185
                    return null;
186
                } else {
187
                    return String.format(Locale.US, "%d Hz", sampleRate);
188
                }
189
            }
190
        });
191
        sFormatterMap.put(KEY_IJK_CHANNEL_UI, new Formatter() {
192
            @Override
193
            protected String doFormat(IjkMediaFormat mediaFormat) {
194
                int channelLayout = mediaFormat.getInteger(IjkMediaMeta.IJKM_KEY_CHANNEL_LAYOUT);
195
                if (channelLayout <= 0) {
196
                    return null;
197
                } else {
198
                    if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_MONO) {
199
                        return "mono";
200
                    } else if (channelLayout == IjkMediaMeta.AV_CH_LAYOUT_STEREO) {
201
                        return "stereo";
202
                    } else {
203
                        return String.format(Locale.US, "%x", channelLayout);
204
                    }
205
                }
206
            }
207
        });
208
    }
209
}

+ 96 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/misc/IjkTrackInfo.java

@ -0,0 +1,96 @@
1
/*
2
 * Copyright (C) 2015 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.misc;
18
19
import android.text.TextUtils;
20
21
import tv.danmaku.ijk.media.player.IjkMediaMeta;
22
23
public class IjkTrackInfo implements ITrackInfo {
24
    private int mTrackType = MEDIA_TRACK_TYPE_UNKNOWN;
25
    private IjkMediaMeta.IjkStreamMeta mStreamMeta;
26
27
    public IjkTrackInfo(IjkMediaMeta.IjkStreamMeta streamMeta) {
28
        mStreamMeta = streamMeta;
29
    }
30
31
    public void setMediaMeta(IjkMediaMeta.IjkStreamMeta streamMeta) {
32
        mStreamMeta = streamMeta;
33
    }
34
35
    @Override
36
    public IMediaFormat getFormat() {
37
        return new IjkMediaFormat(mStreamMeta);
38
    }
39
40
    @Override
41
    public String getLanguage() {
42
        if (mStreamMeta == null || TextUtils.isEmpty(mStreamMeta.mLanguage))
43
            return "und";
44
45
        return mStreamMeta.mLanguage;
46
    }
47
48
    @Override
49
    public int getTrackType() {
50
        return mTrackType;
51
    }
52
53
    public void setTrackType(int trackType) {
54
        mTrackType = trackType;
55
    }
56
57
    @Override
58
    public String toString() {
59
        return getClass().getSimpleName() + '{' + getInfoInline() + "}";
60
    }
61
62
    @Override
63
    public String getInfoInline() {
64
        StringBuilder out = new StringBuilder(128);
65
        switch (mTrackType) {
66
            case MEDIA_TRACK_TYPE_VIDEO:
67
                out.append("VIDEO");
68
                out.append(", ");
69
                out.append(mStreamMeta.getCodecShortNameInline());
70
                out.append(", ");
71
                out.append(mStreamMeta.getBitrateInline());
72
                out.append(", ");
73
                out.append(mStreamMeta.getResolutionInline());
74
                break;
75
            case MEDIA_TRACK_TYPE_AUDIO:
76
                out.append("AUDIO");
77
                out.append(", ");
78
                out.append(mStreamMeta.getCodecShortNameInline());
79
                out.append(", ");
80
                out.append(mStreamMeta.getBitrateInline());
81
                out.append(", ");
82
                out.append(mStreamMeta.getSampleRateInline());
83
                break;
84
            case MEDIA_TRACK_TYPE_TIMEDTEXT:
85
                out.append("TIMEDTEXT");
86
                break;
87
            case MEDIA_TRACK_TYPE_SUBTITLE:
88
                out.append("SUBTITLE");
89
                break;
90
            default:
91
                out.append("UNKNOWN");
92
                break;
93
        }
94
        return out.toString();
95
    }
96
}

+ 142 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/pragma/DebugLog.java

@ -0,0 +1,142 @@
1
/*
2
 * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
package tv.danmaku.ijk.media.player.pragma;
18
19
import java.util.Locale;
20
21
22
import android.util.Log;
23
24
@SuppressWarnings({"SameParameterValue", "WeakerAccess"})
25
public class DebugLog {
26
    public static final boolean ENABLE_ERROR = Pragma.ENABLE_VERBOSE;
27
    public static final boolean ENABLE_INFO = Pragma.ENABLE_VERBOSE;
28
    public static final boolean ENABLE_WARN = Pragma.ENABLE_VERBOSE;
29
    public static final boolean ENABLE_DEBUG = Pragma.ENABLE_VERBOSE;
30
    public static final boolean ENABLE_VERBOSE = Pragma.ENABLE_VERBOSE;
31
32
    public static void e(String tag, String msg) {
33
        if (ENABLE_ERROR) {
34
            Log.e(tag, msg);
35
        }
36
    }
37
38
    public static void e(String tag, String msg, Throwable tr) {
39
        if (ENABLE_ERROR) {
40
            Log.e(tag, msg, tr);
41
        }
42
    }
43
44
    public static void efmt(String tag, String fmt, Object... args) {
45
        if (ENABLE_ERROR) {
46
            String msg = String.format(Locale.US, fmt, args);
47
            Log.e(tag, msg);
48
        }
49
    }
50
51
    public static void i(String tag, String msg) {
52
        if (ENABLE_INFO) {
53
            Log.i(tag, msg);
54
        }
55
    }
56
57
    public static void i(String tag, String msg, Throwable tr) {
58
        if (ENABLE_INFO) {
59
            Log.i(tag, msg, tr);
60
        }
61
    }
62
63
    public static void ifmt(String tag, String fmt, Object... args) {
64
        if (ENABLE_INFO) {
65
            String msg = String.format(Locale.US, fmt, args);
66
            Log.i(tag, msg);
67
        }
68
    }
69
70
    public static void w(String tag, String msg) {
71
        if (ENABLE_WARN) {
72
            Log.w(tag, msg);
73
        }
74
    }
75
76
    public static void w(String tag, String msg, Throwable tr) {
77
        if (ENABLE_WARN) {
78
            Log.w(tag, msg, tr);
79
        }
80
    }
81
82
    public static void wfmt(String tag, String fmt, Object... args) {
83
        if (ENABLE_WARN) {
84
            String msg = String.format(Locale.US, fmt, args);
85
            Log.w(tag, msg);
86
        }
87
    }
88
89
    public static void d(String tag, String msg) {
90
        if (ENABLE_DEBUG) {
91
            Log.d(tag, msg);
92
        }
93
    }
94
95
    public static void d(String tag, String msg, Throwable tr) {
96
        if (ENABLE_DEBUG) {
97
            Log.d(tag, msg, tr);
98
        }
99
    }
100
101
    public static void dfmt(String tag, String fmt, Object... args) {
102
        if (ENABLE_DEBUG) {
103
            String msg = String.format(Locale.US, fmt, args);
104
            Log.d(tag, msg);
105
        }
106
    }
107
108
    public static void v(String tag, String msg) {
109
        if (ENABLE_VERBOSE) {
110
            Log.v(tag, msg);
111
        }
112
    }
113
114
    public static void v(String tag, String msg, Throwable tr) {
115
        if (ENABLE_VERBOSE) {
116
            Log.v(tag, msg, tr);
117
        }
118
    }
119
120
    public static void vfmt(String tag, String fmt, Object... args) {
121
        if (ENABLE_VERBOSE) {
122
            String msg = String.format(Locale.US, fmt, args);
123
            Log.v(tag, msg);
124
        }
125
    }
126
127
    public static void printStackTrace(Throwable e) {
128
        if (ENABLE_WARN) {
129
            e.printStackTrace();
130
        }
131
    }
132
133
    public static void printCause(Throwable e) {
134
        if (ENABLE_WARN) {
135
            Throwable cause = e.getCause();
136
            if (cause != null)
137
                e = cause;
138
139
            printStackTrace(e);
140
        }
141
    }
142
}

+ 23 - 0
ijkplayer-java/src/main/java/tv/danmaku/ijk/media/player/pragma/Pragma.java

@ -0,0 +1,23 @@
1
/*
2
 * Copyright (C) 2013 Zhang Rui <bbcallen@gmail.com>
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package tv.danmaku.ijk.media.player.pragma;
17
18
/*-
19
 * configurated by app project
20
 */
21
public class Pragma {
22
    public static final boolean ENABLE_VERBOSE = true;
23
}

+ 15 - 0
ijkplayer-java/src/main/project.properties

@ -0,0 +1,15 @@
1
# This file is automatically generated by Android Tools.
2
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3
#
4
# This file must be checked in Version Control Systems.
5
#
6
# To customize properties used by the Ant build system edit
7
# "ant.properties", and override values to adapt the script to your
8
# project structure.
9
#
10
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12
13
# Project target.
14
target=android-22
15
android.library=true

+ 6 - 0
ijkplayer-java/src/main/res/values/strings.xml

@ -0,0 +1,6 @@
1
<?xml version="1.0" encoding="utf-8"?>
2
<resources>
3
4
    <string name="ijkplayer_dummy"></string>
5
6
</resources>