1
00:00:00,790 --> 00:00:01,450
Welcome back.

2
00:00:01,630 --> 00:00:07,870
And the last video we prepared this method get bitmap from view, where we just paste a view in and

3
00:00:08,080 --> 00:00:09,490
it will return a bitmap.

4
00:00:09,730 --> 00:00:15,160
And now we're going to look at how we can store such a bitmap onto our device.

5
00:00:15,340 --> 00:00:19,000
And I'm going to create a co-writing, therefore.

6
00:00:19,090 --> 00:00:22,570
So we need to use to suspend keyboard, suspend Fong.

7
00:00:22,570 --> 00:00:25,600
And I'm going to call this method bitmap file.

8
00:00:25,690 --> 00:00:27,520
So we'll safe bitmap file to be precise.

9
00:00:27,820 --> 00:00:29,980
And we need to have a bitmap.

10
00:00:31,750 --> 00:00:36,340
So let's add a bitmap multiple here, which will return a string.

11
00:00:37,810 --> 00:00:42,880
OK, so this will be the structure of our suspend function.

12
00:00:43,570 --> 00:00:48,850
So first of all, I need to create a variable that will contain the result.

13
00:00:48,940 --> 00:00:49,990
So so what?

14
00:00:49,990 --> 00:00:53,320
We're storing the image and then we need to use with context.

15
00:00:53,560 --> 00:00:56,790
And in order to use with context, we need to import with context.

16
00:00:56,800 --> 00:01:04,660
So in order to do that, let's go over to our Gradle file and add the.

17
00:01:05,780 --> 00:01:06,470
Dependencies.

18
00:01:06,770 --> 00:01:10,790
So here we need to make sure that we add the dependency.

19
00:01:10,910 --> 00:01:16,550
So we're in the Gradle file for app, and the dependency that we're going to require is going to be

20
00:01:16,550 --> 00:01:17,290
the activity.

21
00:01:17,300 --> 00:01:18,130
Katy X.

22
00:01:18,680 --> 00:01:20,210
So here implementation.

23
00:01:21,230 --> 00:01:29,750
Android X activity, Kolan activity minus Katy X, and we can use the beta, in my case, beta 01,

24
00:01:30,080 --> 00:01:35,990
so that version here and then we need to sync it, otherwise we cannot use all of this code routine

25
00:01:35,990 --> 00:01:36,380
stuff.

26
00:01:36,680 --> 00:01:37,130
OK?

27
00:01:37,490 --> 00:01:43,070
Once the Gradle is done and the thinking is done, we can go back to the main activity.

28
00:01:45,360 --> 00:01:45,630
OK.

29
00:01:45,720 --> 00:01:46,800
In my case, it's done now.

30
00:01:47,040 --> 00:01:51,090
Now we can use with context or we can import with context.

31
00:01:51,330 --> 00:01:54,780
So let me just go ahead and rewrite it with context.

32
00:01:55,170 --> 00:01:57,000
You can see now I can actually use it.

33
00:01:57,870 --> 00:01:58,220
OK.

34
00:01:58,620 --> 00:02:03,480
And then I need to add the thread that I want to run this on, and I'm going to use the dispatcher's

35
00:02:03,780 --> 00:02:05,730
I, as we have seen in the demo.

36
00:02:05,760 --> 00:02:06,120
OK.

37
00:02:06,150 --> 00:02:12,280
This bettcher's that i o the input output this picture and we are outputting something right?

38
00:02:12,300 --> 00:02:13,340
We're outputting an image.

39
00:02:13,350 --> 00:02:14,580
That's the idea behind this.

40
00:02:15,650 --> 00:02:22,820
Function, so first, we check if the bitmap that is given to us so in bitmap is not equal null because

41
00:02:22,820 --> 00:02:28,220
only if that's the case, then I want this to run because we can call this method with an empty bitmap

42
00:02:28,220 --> 00:02:31,130
and it will just do nothing or it will still work in a way.

43
00:02:31,760 --> 00:02:31,970
OK.

44
00:02:32,090 --> 00:02:38,960
And then because things can go wrong doing what we're going to do, so storing something using output

45
00:02:38,960 --> 00:02:41,600
streams and stuff, we need to use a try block here.

46
00:02:41,870 --> 00:02:49,150
So I will create this variable byte, which will be a byte array output stream.

47
00:02:49,160 --> 00:02:53,570
So we're outputting an image which creates a new byte array output stream.

48
00:02:54,230 --> 00:02:59,510
The buffer capacity is initially 32 bytes, though its size increases if necessary.

49
00:03:00,050 --> 00:03:03,440
So now we can use the bitmap and compress it.

50
00:03:04,310 --> 00:03:11,690
So that's a function that Bitmaps has, and we need to pass in the format that we want to use to quality

51
00:03:11,690 --> 00:03:13,260
and output streams.

52
00:03:13,260 --> 00:03:13,710
So here?

53
00:03:14,030 --> 00:03:18,830
What kind of format do we want to use while we can just use the bitmap compressed format?

54
00:03:18,980 --> 00:03:23,450
So here just go ahead and use bitmap colon compress format.

55
00:03:23,960 --> 00:03:26,270
So it's an item that we can use here.

56
00:03:26,270 --> 00:03:29,630
And then I'm going to say I want to use the PMG format.

57
00:03:30,350 --> 00:03:30,650
All right.

58
00:03:30,650 --> 00:03:32,360
So the image will be stored as a peg.

59
00:03:32,750 --> 00:03:34,730
Then you can say which quality you want to use.

60
00:03:34,730 --> 00:03:38,510
And I'm going to say 90, which is 90 percent, which is a good enough quality.

61
00:03:38,840 --> 00:03:40,310
Very good quality, actually.

62
00:03:40,610 --> 00:03:44,930
So you don't want to overdo it because otherwise the image will just be huge, and I don't think it's

63
00:03:44,930 --> 00:03:46,970
necessary for our application.

64
00:03:47,300 --> 00:03:50,600
And then I'm just going to pass in the output stream.

65
00:03:50,600 --> 00:03:52,820
So byte array output stream.

66
00:03:52,820 --> 00:03:56,330
So Bytes is how I call this, but you could of course, call it differently.

67
00:03:57,020 --> 00:04:04,130
And then now that we are compressing it, we need to create a file out of it so that we can store it

68
00:04:04,130 --> 00:04:06,890
because we can now then used to file output stream.

69
00:04:07,190 --> 00:04:08,720
So let's create a file.

70
00:04:10,260 --> 00:04:18,930
And this will be a file which has a Perth name and can use the external cache directory.

71
00:04:19,440 --> 00:04:19,930
Dot.

72
00:04:19,950 --> 00:04:24,630
And a simple file for a second here or in a second.

73
00:04:24,660 --> 00:04:32,100
OK, so we can get the external cache directory, then the absolute file to string.

74
00:04:33,210 --> 00:04:35,820
So this will give us a location.

75
00:04:37,950 --> 00:04:40,140
Where our application is, so to speak.

76
00:04:40,380 --> 00:04:45,090
So this is going to be the path name which we now add something to.

77
00:04:45,510 --> 00:04:50,200
OK, so this is where it will be on our device, so to speak global and to store the image.

78
00:04:50,490 --> 00:04:54,060
And I'm going to add the file separator.

79
00:04:55,520 --> 00:04:57,620
To it, which is also a string.

80
00:04:58,910 --> 00:05:05,750
So this is the file separator, whatever is used as a file separator could be a dot or whatever, and

81
00:05:05,750 --> 00:05:08,450
then I'm using the name of my application.

82
00:05:08,450 --> 00:05:10,790
I'm just going to call this one case drawing.

83
00:05:12,540 --> 00:05:21,570
Our case drawing app on the score, so you can call it whatever this will just be, how the file will

84
00:05:21,570 --> 00:05:22,890
be called on my system.

85
00:05:23,250 --> 00:05:30,420
And then in order to give each image a unique name, I'm just going to add the current time in milliseconds

86
00:05:30,750 --> 00:05:37,140
divided by 1000 plus and then to type dot PNG.

87
00:05:38,390 --> 00:05:38,810
OK.

88
00:05:39,880 --> 00:05:47,290
So what will now happen is, well, this is basically going to be the location for the file and will

89
00:05:47,290 --> 00:05:48,850
create a file item.

90
00:05:49,240 --> 00:05:55,090
So we're passing where the location is and we're saying, OK, I want this file to be stored with the

91
00:05:55,090 --> 00:05:56,980
name at this location.

92
00:05:58,720 --> 00:05:59,200
And then.

93
00:06:00,370 --> 00:06:04,540
We can create a file output stream.

94
00:06:05,110 --> 00:06:09,460
So file output, stream object and pass our app to it.

95
00:06:09,550 --> 00:06:10,750
So our file to it.

96
00:06:11,470 --> 00:06:13,390
So now we just need to write.

97
00:06:13,690 --> 00:06:22,960
So here let's use bytes thought to byte array so it will take our battery output stream and make about

98
00:06:22,960 --> 00:06:23,950
a ray out of it.

99
00:06:24,640 --> 00:06:26,170
And then we can close it.

100
00:06:26,740 --> 00:06:30,970
So overall, we're creating the file output stream, were writing something and then were closing the

101
00:06:30,970 --> 00:06:36,760
file output stream and release any system resources associated with the stream.

102
00:06:37,300 --> 00:06:37,990
It's really important.

103
00:06:39,070 --> 00:06:41,770
And then we get the actual result.

104
00:06:42,070 --> 00:06:46,300
So here we can assign the result to be that absolute path.

105
00:06:46,720 --> 00:06:49,750
So the absolute path of the file.

106
00:06:51,170 --> 00:06:59,270
So basically, where to fight list and now we can run something on the UI threat because this is a suspend

107
00:06:59,270 --> 00:07:03,800
function, write a code routine function, which means it will run all of this stuff in the background,

108
00:07:03,800 --> 00:07:04,490
which is great.

109
00:07:04,760 --> 00:07:06,650
That's exactly how you're supposed to do it.

110
00:07:06,710 --> 00:07:10,700
Don't run this resource intensive stuff on the main thread on the UI thread.

111
00:07:10,970 --> 00:07:14,930
But what we do want to run on the UI threat is going to be.

112
00:07:16,650 --> 00:07:22,110
Letting the user know where the file was saved because it was saved and the result, right, so we can

113
00:07:22,110 --> 00:07:24,120
just check if result.

114
00:07:26,780 --> 00:07:36,290
That is not empty and it is not empty, so if it's not empty, then we want to write a toast and toast

115
00:07:36,290 --> 00:07:41,140
will just be basically saying where the result is.

116
00:07:41,150 --> 00:07:44,000
So make text file save successfully add result.

117
00:07:44,090 --> 00:07:50,840
So this is the location where it has been stored for a short period of time and otherwise.

118
00:07:50,930 --> 00:07:58,070
So in the case, if result is empty, we're going to say that something went wrong saving the file.

119
00:07:58,070 --> 00:07:59,360
So another toast here.

120
00:07:59,750 --> 00:08:01,730
Something went wrong while saving the file.

121
00:08:02,030 --> 00:08:05,450
Now, because this all can go wrong, this entire try block.

122
00:08:05,930 --> 00:08:11,210
Let's go ahead and add a catch block here, which we catch with an exception.

123
00:08:11,930 --> 00:08:16,070
And we're just going to say in that case, result is going to be an empty string.

124
00:08:19,250 --> 00:08:25,820
And we're going to print to the stack trace, whatever the error has in store for us.

125
00:08:26,510 --> 00:08:31,880
And you see, we still have an error here because we need to return something and we need to return

126
00:08:31,880 --> 00:08:32,600
a string.

127
00:08:32,600 --> 00:08:35,600
And luckily enough result is in fact going to be a string.

128
00:08:36,470 --> 00:08:39,140
So here the result will either be empty.

129
00:08:39,140 --> 00:08:40,669
So it is empty at the beginning.

130
00:08:41,450 --> 00:08:47,630
And in the case that there is an exception, we are really making sure that it's going to be empty.

131
00:08:47,960 --> 00:08:52,730
And if there is no exception and things go right, we are trying to create this file.

132
00:08:53,150 --> 00:08:57,740
And on the UI thread, we are also displaying the results.

133
00:08:58,370 --> 00:09:01,790
And of course, the result will be the path of the file that we created.

134
00:09:01,790 --> 00:09:02,990
So the image that we created.

135
00:09:04,070 --> 00:09:07,430
OK, so now we have this safe bitmap file method.

136
00:09:07,440 --> 00:09:12,410
We have this get bitmap from new method and we have only looked at code for over 20 minutes now.

137
00:09:12,650 --> 00:09:15,860
So let's go ahead and actually make this run.

138
00:09:16,190 --> 00:09:23,670
And in order to make it run, we need to go to the on create method because there I want to use my button,

139
00:09:23,690 --> 00:09:31,880
so my save button and I'm going to call it button save, and it will be the image button safe that we

140
00:09:31,880 --> 00:09:37,250
created in the last video, which is this image button that has this little save icon.

141
00:09:38,090 --> 00:09:38,510
All right.

142
00:09:38,780 --> 00:09:44,630
And then, of course, we need to use the I.B. safe here instead of the I.B. undo.

143
00:09:45,890 --> 00:09:51,800
So let's do that and call a different method in here, so that will be the important part.

144
00:09:52,280 --> 00:09:53,930
So what is it that we want to call?

145
00:09:55,130 --> 00:10:01,610
Well, we want to call or basically we want to execute a call routine.

146
00:10:02,090 --> 00:10:05,960
So what I want to do here is I want to check, can I write to the stories?

147
00:10:06,080 --> 00:10:13,820
And let's go over here and see, OK, we have read external storage, but now let's add uses permission,

148
00:10:14,210 --> 00:10:14,670
right?

149
00:10:14,690 --> 00:10:16,410
External storage here as well.

150
00:10:16,430 --> 00:10:23,570
Like so and then, of course, any we need to make changes to our permission request here.

151
00:10:24,170 --> 00:10:31,310
So we asked for external storage only, but now we need to ask for the other.

152
00:10:32,460 --> 00:10:36,270
One as well amid check for the down.

153
00:10:37,460 --> 00:10:39,740
Well, we showed a Russian nail.

154
00:10:41,440 --> 00:10:43,360
Here what we request storage permission.

155
00:10:44,430 --> 00:10:50,400
OK, so here we have an array of permissions, and you see we have this to do had writing external storage

156
00:10:50,400 --> 00:10:55,720
permission, I added that earlier here we need to go ahead and use manifester.

157
00:10:55,740 --> 00:10:57,960
Permission dot, right?

158
00:10:58,950 --> 00:10:59,610
External.

159
00:11:00,940 --> 00:11:02,020
Or what is it?

160
00:11:02,350 --> 00:11:03,030
Right?

161
00:11:04,070 --> 00:11:06,130
External storage, yeah, that's a.

162
00:11:08,630 --> 00:11:17,750
So how do I now find out if I have the right to read to the storage and basically in later versions

163
00:11:17,750 --> 00:11:19,970
of Android and the latest versions of Android?

164
00:11:20,180 --> 00:11:23,750
You don't need to ask for read and write permissions at the same time.

165
00:11:24,080 --> 00:11:27,990
But we're just making sure that we have both for all the versions.

166
00:11:28,190 --> 00:11:35,540
But what we can now do is we can just go ahead and say private fun is read storage allowed.

167
00:11:36,740 --> 00:11:42,890
Which will return a Boolean, which will just let me know if we do have storage reading right or not.

168
00:11:43,580 --> 00:11:49,850
So what we can do is we can create a variable, which will be the result, and I get it from the context,

169
00:11:49,850 --> 00:11:55,610
composite check, self permission and I need to pass in the context as well as the permission that I

170
00:11:55,610 --> 00:11:57,050
want to check if I have that.

171
00:11:57,470 --> 00:12:03,140
And I can just say manifestantes permission thoughts, read external storage.

172
00:12:03,680 --> 00:12:05,390
So this will give me the result.

173
00:12:05,930 --> 00:12:09,410
And now I just need to return this result as a Boolean.

174
00:12:09,950 --> 00:12:16,310
So return result is equal equal package manager.

175
00:12:18,230 --> 00:12:20,480
Package manager Dot.

176
00:12:21,020 --> 00:12:22,010
Permission granted.

177
00:12:23,330 --> 00:12:30,230
OK, so what we're doing here is we are having an if clause, so to speak, so result will be either

178
00:12:30,230 --> 00:12:34,850
permission granted or not granted, so it will return a true or false statement.

179
00:12:35,540 --> 00:12:41,720
So we're checking for self permission, which will return permission granted or not granted, right?

180
00:12:41,720 --> 00:12:45,660
So static int which returns an integer and permission granted.

181
00:12:45,680 --> 00:12:46,970
What is the integer for that?

182
00:12:47,300 --> 00:12:49,880
You see the permission granted integer is zero.

183
00:12:50,300 --> 00:12:57,710
So if we get zero as a response from this method, call here where we check whether we have external

184
00:12:57,710 --> 00:13:02,720
reading storage permission, then result will be zero and permission.

185
00:13:02,720 --> 00:13:05,210
Granted, this also zero, so it will return true.

186
00:13:05,450 --> 00:13:07,010
Otherwise, it will return false.

187
00:13:07,550 --> 00:13:13,910
So now we can check if we have right or the right to read it from the storage, which also gives us

188
00:13:13,910 --> 00:13:18,230
the right to right to the storage in the latest Android Studio versions and the Android versions.

189
00:13:18,560 --> 00:13:28,280
So here we can just check if is read storage allowed and if that's the case, then I want to launch

190
00:13:28,280 --> 00:13:30,350
my lifecycle scope.

191
00:13:31,280 --> 00:13:33,730
So basically my call routine launch.

192
00:13:34,130 --> 00:13:37,580
Like so and we need to import lifecycle scope here.

193
00:13:38,240 --> 00:13:38,900
Let's do that.

194
00:13:38,900 --> 00:13:46,850
We need to import launch and both of them will be added to here import lifecycle, scope, launch,

195
00:13:47,180 --> 00:13:49,030
dispatcher's and with context.

196
00:13:49,030 --> 00:13:54,020
So all of these here are the call routine related imports.

197
00:13:54,440 --> 00:13:56,990
OK, so just make sure that you have them.

198
00:13:58,160 --> 00:14:02,870
And also, if you don't understand what's up here, definitely check out the ratings demo that I created

199
00:14:03,350 --> 00:14:08,930
a couple of lectures before so we can now get the image from our.

200
00:14:10,880 --> 00:14:11,360
View.

201
00:14:11,450 --> 00:14:13,560
So what view does it have the image?

202
00:14:13,580 --> 00:14:18,440
So what is the view that contains all of the graphics that we have in here?

203
00:14:19,160 --> 00:14:20,090
Well, let's look at it.

204
00:14:21,020 --> 00:14:28,550
So we need to go over to our frame layout and you can see that our frame layout here exists of an image

205
00:14:28,550 --> 00:14:30,020
view and a drawing view.

206
00:14:30,050 --> 00:14:34,880
And a drawing view is our self-created view that we have built, right?

207
00:14:34,880 --> 00:14:37,910
This class, which contains all of the drawing that we did ourselves.

208
00:14:38,570 --> 00:14:43,610
And then it contains the image that we have as the background.

209
00:14:44,120 --> 00:14:49,490
So what we want to do is we want to get this frame layout, which is itself also a view.

210
00:14:49,940 --> 00:14:50,960
We want to get that.

211
00:14:51,140 --> 00:14:52,580
And we want to send which it.

212
00:14:52,670 --> 00:14:56,330
So put those two things together to image, view and whatever we drew.

213
00:14:56,840 --> 00:15:02,400
And we want the stories because that's what all of the methods that we created were for, right?

214
00:15:02,420 --> 00:15:07,950
So our gets bitmap from view, it takes a view.

215
00:15:07,990 --> 00:15:15,800
And for example, we could present the frame layout here, and then it says it to the well, this saves

216
00:15:15,800 --> 00:15:19,100
this bitmap that is created from this view you see here.

217
00:15:19,490 --> 00:15:25,160
It creates a bitmap where passing it to the safe bitmap file, and this method then saves it in the

218
00:15:25,160 --> 00:15:25,610
background.

219
00:15:26,180 --> 00:15:30,980
So let's put all of this together because this is quite advanced stuff, I'd say.

220
00:15:31,310 --> 00:15:36,110
So let's use our full drawing view.

221
00:15:36,410 --> 00:15:40,610
And like so drawing view, which is a frame layout.

222
00:15:41,300 --> 00:15:44,210
So we need to import frame layout here for this to work.

223
00:15:44,900 --> 00:15:55,450
So import frame layout like so and then we can find it by its ID or Dot ID dot drawing view container.

224
00:15:55,640 --> 00:15:58,070
That's how we called this frame layout, right.

225
00:15:58,220 --> 00:16:04,730
This frame layout here, which contains the view and everything is going to be the right.

226
00:16:05,640 --> 00:16:12,270
Item that we want to have, because now what we can do with this AFL drawing view, we can pass it to

227
00:16:12,270 --> 00:16:18,300
our safe bitmap file, get bitmap from you.

228
00:16:19,230 --> 00:16:26,970
Call so what I'm doing here is I'm calling this method, which will return a bitmap and then I'm passing

229
00:16:26,970 --> 00:16:28,950
this bitmap to save bitmap from file.

230
00:16:29,100 --> 00:16:37,230
Of course, you could have gone ahead and said, my bitmap is of type, bitmap is equal to and then

231
00:16:37,230 --> 00:16:42,570
put this here in there and then passed the my bitmap variable.

232
00:16:42,660 --> 00:16:44,130
That would have been fine as well.

233
00:16:44,340 --> 00:16:49,890
If you want to put it into two lines, but of course, you can also just go ahead and do it in one line

234
00:16:50,160 --> 00:16:51,750
and you don't need this line here.

235
00:16:53,440 --> 00:16:59,710
OK, so let's test this as the moment of truth, a bunch of code that we have set up.

236
00:17:00,100 --> 00:17:04,990
Let's see if we can actually store the image onto our device.

237
00:17:09,819 --> 00:17:15,250
OK, so let me draw something safe, and you see, this is where it was stored.

238
00:17:15,760 --> 00:17:19,810
So once again, storage emulated zero Android Datacom.

239
00:17:19,960 --> 00:17:25,270
So it's all of this stuff that we have here like super a long path here.

240
00:17:25,270 --> 00:17:31,360
External cache directory, absolute file to a string, then the file separator and then kid drawing

241
00:17:31,360 --> 00:17:31,570
up.

242
00:17:31,570 --> 00:17:35,920
So once again, just quickly you see it, says Kit Kids drawing up.

243
00:17:35,920 --> 00:17:40,840
So here it's it didn't even say kit drawing app because it was still doing all of this part.

244
00:17:41,200 --> 00:17:42,370
So it's quite a long path.

245
00:17:43,720 --> 00:17:45,640
All right now, how do we get to the image?

246
00:17:45,820 --> 00:17:55,600
Well, we need to go to files and then here as Dickie Android data and then select the path of our application.

247
00:17:55,630 --> 00:18:01,090
So come the kids drawing app cache, and that's where it's stored all of those images.

248
00:18:01,690 --> 00:18:08,830
So let's go back to the application and not the photos app, but to our drawing app, and then let me

249
00:18:08,830 --> 00:18:10,080
select a different image.

250
00:18:11,200 --> 00:18:12,550
Here, let me select Homer.

251
00:18:14,980 --> 00:18:17,950
Like, so OK, then let me draw something.

252
00:18:18,930 --> 00:18:27,120
On top of his head, then save this and go over to the cash folder and we will find our Homer Simpson

253
00:18:27,660 --> 00:18:30,300
with this little bubble around his head.

254
00:18:31,080 --> 00:18:32,400
And yeah, that's pretty much it.

255
00:18:32,760 --> 00:18:36,930
So now you know how to store your image on to your device.

256
00:18:37,290 --> 00:18:38,850
All right, so see you in the next video.

