Hope you don't mind me walking through your problem (as I understand it).
You have an array of 32 bytes, each using only the values 0 or 1. Right? You could think of that using this sort of syntax. (If you really only have 31, not 32, this becomes much easier if you actually add a zero at the left end, to make it 32, a number divisible by four.)
byte mybits[32] = { 1,0,0,1, 0,1,1,0, 1,1,0,0, 0,0,0,1, . . . };
You want to print the binary as hexadecimal digits? A hexadecimal digit represents four bits, called a nibble or nybble. You want to squish four 1-or-0 bytes into four bits. So 1,0,0,1 turns into binary 1001 (or hexadecimal 9). And so on. Right?
You're on the right track, cramming powers of two. But you only need four at a time. If the four bytes are a,b,c,d, then to get the nibble value:
nibble = (a<<3) + (b<<2) + (c<<1) + d;
Once you have a nibble value from hexadecimal 0 to hexadecimal F, you can convert that nibble to a character ready for printing directly.
static const char* _hexdigits = "0123456789ABCDEF";
Now _hexdigits[nibble] gives you the printable character for the nibble value.
Lastly, we loop through the bigger array of bytes you have.
for (int i = 0; i < 32; i += 4)
{
int nibble = (mybits[i] << 3);
nibble += (mybits[i+1] << 2);
nibble += (mybits[i+2] << 1);
nibble += (mybits[i+3]);
Serial.print(_hexdigits[nibble]);
}